]> git.immae.eu Git - perso/Denise/oms.git/blame - gestion_donnees.py
Changement de format pour l'export, ajout des boutons qui vont avec + divers
[perso/Denise/oms.git] / gestion_donnees.py
CommitLineData
5679dfd0
DL
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4from configuration import *
5from gestion_erreurs import *
6import datetime
be2bf515
DL
7import json
8import unidecode
5679dfd0
DL
9
10
11############ Fonctions de conversion
12
13def convertit_jours_vers_python(chaine,liste_err):
14 """ convertit une chaine de type 1a 3m 1s 10j en jours
be2bf515 15 Renvoie un nombre de jours en float
5679dfd0
DL
16 Si un des caractères n'est ni un nombre, ni une lettre "autorisée" ni une espace,
17 on affiche un warning et on ignore ce caractère
18 """
19 chainenombre = ""
20 agejours = 0.
21 for lettre in chaine:
22 if lettre.isdigit():
23 chainenombre += lettre
24 else:
25 if lettre == 'a' or lettre == 'A':
26 # On a trouvé l'année, on ajoute tout ce qui est trouvé jusque là
27 agejours += int(chainenombre)*jours_dans_annee
28 chainenombre = ""
29 elif lettre == 'm' or lettre == 'M':
30 # On a trouvé le mois
31 agejours += int(chainenombre)*jours_dans_mois
32 chainenombre = ""
33 elif lettre == 's' or lettre == 'S':
34 # la semaine
35 agejours += int(chainenombre)*jours_dans_semaine
36 chainenombre = ""
37 elif lettre == 'j' or lettre == 'J':
38 # On a trouvé le jour
39 agejours += int(chainenombre)
40 chainenombre = ""
41 elif lettre != ' ':
42 # autre caractère : bizarre ?
43 warning("convertit_jour_vers_python : caractère invalide : "+lettre,liste_err)
44 # à la fin s'il reste qqch on le garde dans les jours
45 if chainenombre != "":
be2bf515 46 agejours += int(chainenombre)
5679dfd0
DL
47 if agejours<0:
48 warning("L'âge est négatif !",liste_err)
49 agejours = 0
be2bf515 50 return agejours
5679dfd0
DL
51
52def convertit_age_vers_texte(nombre):
53 """ convertit un nombre de jours en un truc plus lisible en mois, années, jours
54 et renvoie une chaîne sous la forme 3a2m1j par exemple"""
55 annees = int(nombre / jours_dans_annee)
be2bf515 56 restant = nombre - annees*jours_dans_annee
5679dfd0 57 mois = int(restant/jours_dans_mois)
be2bf515 58 jours= round(nombre - mois*jours_dans_mois - annees*jours_dans_annee)
5679dfd0
DL
59
60 chaine = ""
61 if annees >0:
62 chaine += str(annees)+"a"
63 if mois >0:
64 chaine += str(mois)+"m"
65 if jours>0 or nombre ==0: # si c'est la naissance, faut beien écrire 0j quand même
66 chaine += str(jours)+"j"
67 return chaine
68##########################
be2bf515
DL
69
70
71def simplifie_nom(chaine):
72 """ simplifie le nom chaine afin d'en faire une extension
73 pour le nom du fichier. Met tout en minuscules et vire les caractères spéciaux
74 et max 15 caractères"""
75 chaine2 = ""
76 for l in chaine:
77 if l.isalpha():
78 chaine2+=l
79 chaine2 = unidecode.unidecode(chaine2)
80 return chaine2[:15]
5679dfd0
DL
81
82def convertit_poids_vers_python(chaine,liste_err):
83 """ convertit une chaine vers un float qui est le poids.
84 On gère notamment la virgule, et on enlève les espaces
85 Un poids invalide -> on renvoie 0 avec un warning"""
86 chaine2 = chaine.replace(",",".")
87 chaine2 = chaine2.replace(" ","")
88
89 try:
66a3e38c 90 poids = float(chaine2)
5679dfd0
DL
91 except:
92 warning("Poids impossible à lire : "+chaine,liste_err)
93 poids = 0
66a3e38c
DL
94 if not( 0<=poids<poids_maxi):
95 warning("Poids incohérent : "+str(poids),liste_err)
5679dfd0
DL
96 poids = 0
97 return poids
98
be2bf515
DL
99#def convertit_poids_vers_texte(poids):
100# """ convertit un poids vers du texte. Rien à dire là pour l'instant """
101# return str(poids)
5679dfd0
DL
102
103#########################
104
105def convertit_date_vers_python(chaine,liste_err):
106 """ prend une chaine comme renvoyée par un champ de formulaire date
107 aaaa-mm-jj et en fait une date python
108 renvoie "" si ne marche pas"""
109 liste = chaine.split("-")
110 if len(liste) != 3:
111 warning("La date : "+chaine+" est invalide !",liste_err)
112 return ""
113 else:
9cb3c31c
DL
114 try:
115 date = datetime.date(int(liste[0]),int(liste[1]),int(liste[2]))
116 except:
117 date = ""
be2bf515 118 warning("Impossible de lire la date "+chaine,liste_err)
9cb3c31c 119 return date
5679dfd0
DL
120
121def convertit_date_vers_texte(date):
122 """ convertit une date python en format texte aaaa-mm-jj"""
123 if date == "":
124 return ""
125 else:
126 return (str(date.year)+"-"+str(date.month)+"-"+str(date.day))
127
128
129def delta_date(date1,datenaissance):
130 """ renvoie le nombre de jours (entier) entre date1 et datenaissance format "datetime"
131 datenaissance est supposée antérieure. Erreur sinon."""
132 d = date1 - datenaissance
133 jours = d.days
134 if jours<0:
135 erreur_continue("La différence entre les dates est négative... :/")
136 return -1
137 return jours
138
139
140########### Fonctions qui gèretn les données
141
142
143def gere_configuration(data,liste_err):
be2bf515 144 """ prend en argument le dictionnaire de requête (configuration imparfaite), et
5679dfd0
DL
145 construit le dictionnaire de configuration qui va bien.
146 Vérifie que chaque entrée est cohérente évidemment."""
147 configuration = {}
148
149 # Pour le nom, osef qu'il soit vide
150 nom = data.get("nom","")
151 # Par contre s'il est trop long on le tronque
152 configuration["nom"] = nom[:longueur_max_nom_bebe]
153
154 sexe = data.get("sexe","")
a46e1269 155 if not (sexe in ["F","M","N"]):
5679dfd0 156 warning("Le sexe de l'enfant est invalide ! "+sexe,liste_err)
a46e1269 157 sexe = "N"
5679dfd0
DL
158 configuration["sexe"] = sexe
159
160 naissance = data.get("naissance","")
161 if naissance !="":
162 naissance = convertit_date_vers_python(naissance,liste_err)
163 configuration["naissance"] = naissance
164
165 # Type de courbe. Au pire on met P
166 tyc = data.get("typecourbe","")
167 if not (tyc in ["P","Z"]):
168 tyc = "P"
169 configuration["typecourbe"] = tyc
170
171 # unité
172 unite = data.get("unite","")
173 if not (unite in liste_unites_valides):
174 unite = ""
175 #warning("L'unité "+unite+" n'est pas reconnue !",liste_err)
176 configuration["unite"] = unite
177
178 # grille
179 grille = data.get("grille","")
180 if grille != "on":
181 configuration["grille"] = ""
182 else:
183 configuration["grille"] = "oui"
184
185 # maxi. 0 signifie qu'on veut pas de maxi
186 maxi = data.get("maxi","")
187 if maxi == "":
188 configuration["maxi"] = 0
189 else:
190 configuration["maxi"] = convertit_jours_vers_python(maxi,liste_err)
191
192 # dimensions du graphique
be2bf515 193 largeur = data.get("largeur","")
5679dfd0
DL
194 if largeur == "":
195 largeur = largeur_graphique
196 else:
197 try:
198 largeur = int(largeur)
199 except:
200 warning("La largeur "+largeur+"est invalide !",liste_err)
201 largeur = largeur_graphique
202 if largeur > largeur_graphique_max:
203 largeur = largeur_graphique_max
204 warning("Largeur trop grande !",liste_err)
205 elif largeur < largeur_graphique_min:
206 largeur = largeur_graphique_min
207 warning("Largeur trop petite !",liste_err)
208 configuration["largeur"] = largeur
209
be2bf515 210 hauteur = data.get("hauteur","")
5679dfd0
DL
211 if hauteur == "":
212 hauteur = hauteur_graphique
213 else:
214 try:
215 hauteur = int(hauteur)
216 except:
217 warning("La hauteur "+hauteur+"est invalide !",liste_err)
218 hauteur = hauteur_graphique
219 if hauteur > hauteur_graphique_max:
220 hauteur = hauteur_graphique_max
221 warning("Hauteur trop grande !",liste_err)
222 elif hauteur < hauteur_graphique_min:
223 hauteur = hauteur_graphique_min
224 warning("Hauteur trop petite !",liste_err)
225 configuration["hauteur"] = hauteur
226
227 # existence et position de la légende
228 legende = data.get("legende","")
229 if legende =="":
230 legende = "non"
231 elif legende=="on":
232 legende = "oui"
233 else:
234 legende = "oui"
235 configuration["legende"] = legende
236
237 positionlegende = data.get("positionlegende","")
238 if not(positionlegende in ['upper left','upper right','lower left','lower right']):
239 positionlegende = "upper left"
240 configuration["positionlegende"] = positionlegende
241
5679dfd0
DL
242 return configuration
243
be2bf515
DL
244#def configuration_vers_texte(config):
245# """ exporte le texte associé à une configuration
246# on dumpe simplement sauf pour maxi """
247# texte = "# Section configuration\n"
248# for (cle,val) in config.items():
249# if cle != "maxi":
250# texte+= cle + "=" + str(val) + "\n"
251# else:
252# texte+= cle + "=" + convertit_age_vers_texte(val)+"\n"
253# texte +="\n"
254# return texte
5679dfd0
DL
255
256
257def gere_donneespoids(data,naissance,liste_err):
258 """ prend en argument le dictionnaire de requête, et la date de naissance
259 (éventuellement vide) et construit les deux listes l_jours et l_poids"""
260
261 # On construit la liste des couples
262 liste_donnees = []
263
264 i = 0
265 # On va chercher si y'a des données à poids_i
266 while "poids_"+str(i) in data.keys():
267 if data["poids_"+str(i)] != "":
268 poids = convertit_poids_vers_python(data["poids_"+str(i)],liste_err)
269 age = data.get("age_"+str(i),"")
270 if age !="":
271 age = convertit_jours_vers_python(age,liste_err)
272 liste_donnees.append((age,poids))
273 else:
274 date = data.get("date_"+str(i),"")
275 datep = convertit_date_vers_python(date,liste_err)
276 # on vérifie la date
277 if naissance == "":
278 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)
279 elif datep != "": # la date est valide et on a une date de naissance
280 age = delta_date(datep,naissance)
281 liste_donnees.append((age,poids))
282 i+=1
283
284 # Trier la liste
285 liste_donnees.sort(key=lambda x : x[0])
286
287 # splitter la liste
288 l_jours = [x[0] for x in liste_donnees]
289 l_poids = [x[1] for x in liste_donnees]
290
291 return (l_jours,l_poids)
292
293
be2bf515
DL
294#def donnees_poids_vers_texte(l_jours,l_poids):
295# """ retourne le texte correspondant aux données de poids """
296# texte = "# Section données\n"
297#
298# for i in range(len(l_poids)):
299# texte +=convertit_age_vers_texte(l_jours[i])+","+convertit_poids_vers_texte(l_poids[i])+"\n"
300#
301# texte+="\n"
302# return texte
303
304
305
306
307
308def donnees_vers_json(l_jours,l_poids,config):
309 """ retourne le json à renvoyer"""
310 gros_dico = config.copy()
311 l_jours2 = [convertit_age_vers_texte(d) for d in l_jours]
312 gros_dico["data_j"] = l_jours2
313 gros_dico["data_p"] = l_poids
314 # gérer la date de naissance
315 if gros_dico.get("naissance","") != "":
316 gros_dico["naissance"] = convertit_date_vers_texte(gros_dico["naissance"])
317 # gérer l'age maxi
318 gros_dico["maxi"] = convertit_age_vers_texte(gros_dico["maxi"])
5679dfd0 319
be2bf515 320 return json.dumps(gros_dico, indent=2,ensure_ascii=False )
5679dfd0 321
be2bf515
DL
322#def fichier_texte_vers_configdonnees(fichier,liste_err):
323# """ prend le texte importé et l'exporte vers configuration et données
324# sous forme de valeurs du formulaire """
325#
326# valform = {}
327# indice_formulaire = 0 # l'indice du formulaire pour les données : age_1, date_1, poids_1 etc
328# num_ligne = 0
329# lignes = fichier.readlines()
330# for ligne in lignes:
331# num_ligne +=1
332# ligne = str(ligne,"utf8")
333# ligne = ligne.rstrip("\n")
334# if ligne != "" and ligne[0] != "#" and not(ligne.isspace()): # les lignes commençant par # sont des commentaires
335# # On essaie de partitionner pour voir
336# (var,egal,val) = ligne.partition("=")
337# if egal == "=": # c'est une ligne de config
338# valform[var] = val
339# else:
340# (age,virgule,poids) = ligne.partition(",") # On partitionne avec ,
341# if virgule == ",":
342# # c'est une ligne de data
343# valform["age_"+str(indice_formulaire)] = age
344# valform["poids_"+str(indice_formulaire)] = poids
345# indice_formulaire +=1
346#
347# else:
348# warning("La ligne "+str(num_ligne)+" n'est pas reconnue et sera ignorée : <"+ligne+">",liste_err)
349#
350# #le nb max du formulaire
351# valform["nb_data"] = max(indice_formulaire +2,nombre_lignes_form)
352#
353# return valform
5679dfd0 354
be2bf515
DL
355def fichier_json_vers_configdonnees(fichier,liste_err):
356 """ prend le json importé et l'exporte vers les valeurs du formulaire """
357 chaine = fichier.read()
358 valform = json.loads(chaine)
359 # Il faut maintenant récupérer les l_jours et l_poids puis les remettre
360 # sous forme de age_i et poids_i
361 l_jours= valform.get("data_j",[])
362 l_poids=valform.get("data_p",[])
363 if len(l_poids) != len(l_jours):
364 warning("Lecture du json : les données sont incohérentes (listes de taille différentes et/ou pb de lecture")
365 long = min(len(l_jours),len(l_poids))
366 else:
367 long = len(l_jours)
368 for i in range(long):
369 valform["age_"+str(i)] = l_jours[i]
370 valform["poids_"+str(i)] = l_poids[i]
371
372 valform["nb_data"] = max(long +2,nombre_lignes_form)
5679dfd0 373
be2bf515 374 return valform
5679dfd0 375
5679dfd0 376
be2bf515 377