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