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