]> git.immae.eu Git - perso/Denise/oms.git/blob - gestion_donnees.py
a2d0a1e2b819431a83391243e9764a62613dd7ff
[perso/Denise/oms.git] / gestion_donnees.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3
4 from configuration import *
5 from gestion_erreurs import *
6 import datetime
7 import json
8 import unidecode
9
10
11 ############ Fonctions de conversion
12
13 def convertit_jours_vers_python(chaine,liste_err):
14 """ convertit une chaine de type 1a 3m 1s 10j en jours
15 Renvoie un nombre de jours en float
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 != "":
46 agejours += int(chainenombre)
47 if agejours<0:
48 warning("L'âge est négatif !",liste_err)
49 agejours = 0
50 return agejours
51
52 def 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)
56 restant = nombre - annees*jours_dans_annee
57 mois = int(restant/jours_dans_mois)
58 jours= round(nombre - mois*jours_dans_mois - annees*jours_dans_annee)
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 ##########################
69
70
71 def 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]
81
82 def 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:
90 poids = float(chaine2)
91 except:
92 warning("Poids impossible à lire : "+chaine,liste_err)
93 poids = 0
94 if not( 0<=poids<poids_maxi):
95 warning("Poids incohérent : "+str(poids),liste_err)
96 poids = 0
97 return poids
98
99 #def convertit_poids_vers_texte(poids):
100 # """ convertit un poids vers du texte. Rien à dire là pour l'instant """
101 # return str(poids)
102
103 #########################
104
105 def 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:
114 try:
115 date = datetime.date(int(liste[0]),int(liste[1]),int(liste[2]))
116 except:
117 date = ""
118 warning("Impossible de lire la date "+chaine,liste_err)
119 return date
120
121 def 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
129 def 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
143 def gere_configuration(data,liste_err):
144 """ prend en argument le dictionnaire de requête (configuration imparfaite), et
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","")
155 if not (sexe in ["F","M","N"]):
156 warning("Le sexe de l'enfant est invalide ! "+sexe,liste_err)
157 sexe = "N"
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
193 largeur = data.get("largeur","")
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
210 hauteur = data.get("hauteur","")
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
242 return configuration
243
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
255
256
257 def 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
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
308 def 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"])
319
320 return json.dumps(gros_dico, indent=2,ensure_ascii=False )
321
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
354
355 def 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)
373
374 return valform
375
376
377