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