Docfile commited on
Commit
9b8923c
·
verified ·
1 Parent(s): 3762b2b

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -449
app.py DELETED
@@ -1,449 +0,0 @@
1
- from flask import Flask, render_template, request, send_file
2
- import os
3
- import convertapi
4
- from docx import Document
5
- from docx.shared import Pt, Cm, RGBColor
6
- from docx.enum.text import WD_ALIGN_PARAGRAPH
7
- from docx.enum.table import WD_TABLE_ALIGNMENT
8
- from docx.oxml.ns import nsdecls
9
- from docx.oxml import parse_xml
10
- from docx.enum.style import WD_STYLE_TYPE
11
-
12
- # Configuration des identifiants ConvertAPI
13
- convertapi.api_credentials = 'secret_8wCI6pgOP9AxLVJG'
14
-
15
- class EvaluationGymnique:
16
- def __init__(self):
17
- self.document = Document()
18
- self.document.sections[0].page_height = Cm(29.7)
19
- self.document.sections[0].page_width = Cm(21)
20
- self.document.sections[0].left_margin = Cm(1.5)
21
- self.document.sections[0].right_margin = Cm(1.5)
22
- self.document.sections[0].top_margin = Cm(1)
23
- self.document.sections[0].bottom_margin = Cm(1)
24
-
25
- # Appliquer des styles généraux (personnalisation des polices et couleurs)
26
- self.appliquer_styles_generaux()
27
-
28
- # Informations d'en-tête par défaut
29
- self.centre_examen = "Centre d'examen"
30
- self.type_examen = "Bac Général"
31
- self.serie = "Série"
32
- self.etablissement = "Établissement"
33
- self.session = "2025"
34
- self.nom_candidat = "Candidat"
35
-
36
- # Liste vide pour les éléments techniques
37
- self.elements_techniques = []
38
- self.appreciations = ["M", "PM", "NM", "NR"]
39
-
40
- def appliquer_styles_generaux(self):
41
- # Modifier le style Normal pour un rendu moderne
42
- style = self.document.styles['Normal']
43
- style.font.name = 'Calibri'
44
- style.font.size = Pt(11)
45
-
46
- # Créer (ou réutiliser) un style personnalisé pour les titres
47
- try:
48
- custom_heading = self.document.styles.add_style('CustomHeading', WD_STYLE_TYPE.PARAGRAPH)
49
- except Exception:
50
- custom_heading = self.document.styles['Heading 1']
51
- custom_heading.font.name = 'Arial'
52
- custom_heading.font.size = Pt(16)
53
- custom_heading.font.bold = True
54
- custom_heading.font.color.rgb = RGBColor(0, 32, 96)
55
-
56
- def ajouter_entete_colore(self):
57
- header_paragraph = self.document.add_paragraph()
58
- header_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
59
- header_paragraph.space_after = Pt(6)
60
- header_run = header_paragraph.add_run("ÉVALUATION GYMNASTIQUE")
61
- header_run.bold = True
62
- header_run.font.size = Pt(14)
63
- header_run.font.color.rgb = RGBColor(0, 32, 96)
64
-
65
- header_table = self.document.add_table(rows=3, cols=2)
66
- header_table.style = 'Table Grid'
67
- header_table.autofit = False
68
-
69
- # Configuration de la hauteur des lignes et ajout de shading sur chaque cellule
70
- for row in header_table.rows:
71
- row.height = Cm(0.8)
72
- for cell in row.cells:
73
- shading_elm = parse_xml(f'<w:shd {nsdecls("w")} w:fill="D9E2F3"/>')
74
- cell._tc.get_or_add_tcPr().append(shading_elm)
75
-
76
- # Première ligne
77
- cell = header_table.cell(0, 0)
78
- paragraph = cell.paragraphs[0]
79
- run = paragraph.add_run("Centre d'examen: ")
80
- run.bold = True
81
- run.font.size = Pt(10)
82
- run.font.color.rgb = RGBColor(0, 32, 96)
83
- paragraph.add_run(self.centre_examen).font.size = Pt(10)
84
-
85
- cell = header_table.cell(0, 1)
86
- paragraph = cell.paragraphs[0]
87
- run = paragraph.add_run("Examen: ")
88
- run.bold = True
89
- run.font.size = Pt(10)
90
- run.font.color.rgb = RGBColor(0, 32, 96)
91
- paragraph.add_run(self.type_examen).font.size = Pt(10)
92
-
93
- # Deuxième ligne
94
- cell = header_table.cell(1, 0)
95
- paragraph = cell.paragraphs[0]
96
- run = paragraph.add_run("Série: ")
97
- run.bold = True
98
- run.font.size = Pt(10)
99
- run.font.color.rgb = RGBColor(0, 32, 96)
100
- paragraph.add_run(self.serie).font.size = Pt(10)
101
-
102
- cell = header_table.cell(1, 1)
103
- paragraph = cell.paragraphs[0]
104
- run = paragraph.add_run("Établissement: ")
105
- run.bold = True
106
- run.font.size = Pt(10)
107
- run.font.color.rgb = RGBColor(0, 32, 96)
108
- paragraph.add_run(self.etablissement).font.size = Pt(10)
109
-
110
- # Troisième ligne
111
- cell = header_table.cell(2, 0)
112
- paragraph = cell.paragraphs[0]
113
- run = paragraph.add_run("Session: ")
114
- run.bold = True
115
- run.font.size = Pt(10)
116
- run.font.color.rgb = RGBColor(0, 32, 96)
117
- paragraph.add_run(self.session).font.size = Pt(10)
118
-
119
- cell = header_table.cell(2, 1)
120
- paragraph = cell.paragraphs[0]
121
- run = paragraph.add_run("Candidat: ")
122
- run.bold = True
123
- run.font.size = Pt(10)
124
- run.font.color.rgb = RGBColor(0, 32, 96)
125
- paragraph.add_run(self.nom_candidat).font.size = Pt(10)
126
-
127
- self.document.add_paragraph().space_after = Pt(4)
128
-
129
- def creer_tableau_elements(self):
130
- # Création d'un tableau pour les éléments techniques avec une mise en forme améliorée
131
- table = self.document.add_table(rows=len(self.elements_techniques) + 1, cols=5)
132
- table.style = 'Table Grid'
133
- table.alignment = WD_TABLE_ALIGNMENT.CENTER
134
-
135
- # Définir les largeurs de colonnes pour une meilleure lisibilité
136
- col_widths = [Cm(8), Cm(3), Cm(2), Cm(2.5), Cm(2.5)]
137
- for col_idx, width in enumerate(col_widths):
138
- for cell in table.columns[col_idx].cells:
139
- cell.width = width
140
-
141
- # Ajustement de la hauteur des lignes et espacement interne
142
- for row in table.rows:
143
- row.height = Cm(1)
144
- for cell in row.cells:
145
- for paragraph in cell.paragraphs:
146
- paragraph.paragraph_format.space_before = Pt(2)
147
- paragraph.paragraph_format.space_after = Pt(2)
148
-
149
- # En-tête du tableau avec arrière-plan personnalisé
150
- header_row = table.rows[0]
151
- for cell in header_row.cells:
152
- shading_elm = parse_xml(f'<w:shd {nsdecls("w")} w:fill="BDD7EE"/>')
153
- cell._tc.get_or_add_tcPr().append(shading_elm)
154
-
155
- headers = ["ELEMENTS TECHNIQUES", "CATEGORIES D'ELEMENTS TECHNIQUES ET PONDERATION", "", "APPRECIATIONS", "POINTS Accordés"]
156
- for i, header in enumerate(headers):
157
- cell = table.cell(0, i)
158
- cell.text = header
159
- cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
160
- run = cell.paragraphs[0].runs[0]
161
- run.bold = True
162
- run.font.size = Pt(9)
163
- run.font.color.rgb = RGBColor(0, 32, 96)
164
- # Fusionner les deux cellules centrales de l'en-tête
165
- table.cell(0, 1).merge(table.cell(0, 2))
166
-
167
- # Remplissage du tableau avec les éléments techniques
168
- for i, element in enumerate(self.elements_techniques, 1):
169
- # Colonne nom de l'élément
170
- element_cell = table.cell(i, 0)
171
- element_cell.text = element["nom"]
172
- element_cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT
173
- run = element_cell.paragraphs[0].runs[0]
174
- run.bold = True
175
- run.font.size = Pt(9)
176
-
177
- # Colonne catégorie
178
- categorie_cell = table.cell(i, 1)
179
- categorie_cell.text = element["categorie"]
180
- categorie_cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
181
- run = categorie_cell.paragraphs[0].runs[0]
182
- run.bold = True
183
- run.font.size = Pt(9)
184
- run.italic = True
185
-
186
- # Colonne points (vous pouvez ajouter ici d'autres colonnes selon vos besoins)
187
- points_cell = table.cell(i, 2)
188
- points_cell.text = str(element["points"])
189
- points_cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
190
- run = points_cell.paragraphs[0].runs[0]
191
- run.bold = True
192
- run.font.size = Pt(9)
193
- run.italic = True
194
-
195
- def ajouter_note_jury(self):
196
- para = self.document.add_paragraph()
197
- para.space_before = Pt(4)
198
- para.space_after = Pt(4)
199
- run = para.add_run("NB1 : Zone réservée aux membres du jury ! Le jury cochera le point correspondant au niveau de réalisation de l'élément gymnique par le candidat.")
200
- run.bold = True
201
- run.font.color.rgb = RGBColor(255, 0, 0)
202
- run.font.size = Pt(9)
203
-
204
- def creer_tableau_recapitulatif(self):
205
- note_table = self.document.add_table(rows=3, cols=13)
206
- note_table.style = 'Table Grid'
207
- note_table.alignment = WD_TABLE_ALIGNMENT.CENTER
208
-
209
- for row in note_table.rows:
210
- row.height = Cm(0.6)
211
- for cell in note_table.rows[0].cells:
212
- shading_elm = parse_xml(f'<w:shd {nsdecls("w")} w:fill="BDD7EE"/>')
213
- cell._tc.get_or_add_tcPr().append(shading_elm)
214
-
215
- for col, (type_lettre, points) in enumerate([("A", "1pt"), ("B", "1,5pt"), ("C", "2pts"), ("D", "2,5pts"), ("E", "3pts")]):
216
- idx = col * 2
217
- if idx + 1 < len(note_table.columns):
218
- cell = note_table.cell(0, idx)
219
- cell.merge(note_table.cell(0, idx + 1))
220
- cell.text = f"Type {type_lettre}\n{points}"
221
- cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
222
- for run in cell.paragraphs[0].runs:
223
- run.bold = True
224
- run.font.size = Pt(9)
225
- run.font.color.rgb = RGBColor(0, 32, 96)
226
-
227
- for col, (titre, points) in enumerate([("ROV", "2pts"), ("Projet", "2pts"), ("Réalisation", "16pts")], 10):
228
- if col < len(note_table.columns):
229
- cell = note_table.cell(0, col)
230
- cell.text = f"{titre}\n{points}"
231
- cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
232
- for run in cell.paragraphs[0].runs:
233
- run.bold = True
234
- run.font.size = Pt(9)
235
- run.font.color.rgb = RGBColor(0, 32, 96)
236
-
237
- for col in range(5):
238
- idx = col * 2
239
- if idx + 1 < len(note_table.columns):
240
- neg_cell = note_table.cell(1, idx)
241
- neg_cell.text = "NEG"
242
- neg_cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
243
- for run in neg_cell.paragraphs[0].runs:
244
- run.italic = True
245
- run.font.size = Pt(9)
246
-
247
- note_cell = note_table.cell(1, idx + 1)
248
- note_cell.text = "Note"
249
- note_cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
250
- for run in note_cell.paragraphs[0].runs:
251
- run.italic = True
252
- run.font.size = Pt(9)
253
-
254
- for col in range(10, 13):
255
- if col < len(note_table.columns):
256
- cell = note_table.cell(1, col)
257
- cell.text = "Note"
258
- cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
259
- for run in cell.paragraphs[0].runs:
260
- run.italic = True
261
- run.font.size = Pt(9)
262
-
263
- for col, type_lettre in enumerate(["A", "B", "C", "D", "E"]):
264
- idx = col * 2
265
- if idx < len(note_table.columns):
266
- neg_cell = note_table.cell(2, idx)
267
- neg_cell.text = ""
268
- neg_cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
269
-
270
- def ajouter_accolade(self):
271
- # Créer un tableau pour simuler l'accolade
272
- accolade_table = self.document.add_table(rows=1, cols=3)
273
- accolade_table.alignment = WD_TABLE_ALIGNMENT.CENTER
274
-
275
- # Supprimer les bordures (simulation)
276
- for cell in accolade_table.rows[0].cells:
277
- cell.border_width = 0
278
-
279
- # Définir les largeurs des cellules
280
- accolade_table.columns[0].width = Cm(8)
281
- accolade_table.columns[1].width = Cm(2)
282
- accolade_table.columns[2].width = Cm(8)
283
-
284
- cell = accolade_table.cell(0, 1)
285
- paragraph = cell.paragraphs[0]
286
- paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
287
- run = paragraph.add_run("}")
288
- run.font.size = Pt(48)
289
- run.font.bold = True
290
-
291
- # Rotation du symbole grâce à une modification XML
292
- from docx.oxml import OxmlElement
293
- from docx.oxml.ns import qn
294
- rPr = run._element.get_or_add_rPr()
295
- rotation = OxmlElement('w:eastAsianLayout')
296
- rotation.set(qn('w:vert'), 'eaVert270')
297
- rPr.append(rotation)
298
-
299
- accolade_table.rows[0].height = Cm(3)
300
-
301
- def ajouter_zone_note(self):
302
- # Tableau pour la note finale avec bordure verte
303
- zone_note = self.document.add_table(rows=1, cols=1)
304
- zone_note.style = 'Table Grid'
305
- zone_note.alignment = WD_TABLE_ALIGNMENT.CENTER
306
-
307
- cell = zone_note.cell(0, 0)
308
- cell.width = Cm(5)
309
- zone_note.rows[0].height = Cm(2)
310
-
311
- from docx.oxml import OxmlElement
312
- from docx.oxml.ns import qn
313
- tc_borders = cell._tc.get_or_add_tcPr().get_or_add_tcBorders()
314
- for border in ['top', 'left', 'bottom', 'right']:
315
- border_elm = OxmlElement(f'w:{border}')
316
- border_elm.set(qn('w:val'), 'single')
317
- border_elm.set(qn('w:sz'), '8')
318
- border_elm.set(qn('w:space'), '0')
319
- border_elm.set(qn('w:color'), '92D050')
320
- tc_borders.append(border_elm)
321
-
322
- p = cell.paragraphs[0]
323
- p.alignment = WD_ALIGN_PARAGRAPH.CENTER
324
- run = p.add_run("Note finale/20")
325
- run.bold = True
326
- run.font.size = Pt(14)
327
- run.font.color.rgb = RGBColor(0, 0, 0)
328
-
329
- self.document.add_paragraph().space_after = Pt(12)
330
-
331
- def ajouter_note_candidat_avec_cadre(self):
332
- note_table = self.document.add_table(rows=1, cols=1)
333
- note_table.style = 'Table Grid'
334
- note_table.alignment = WD_TABLE_ALIGNMENT.CENTER
335
-
336
- cell = note_table.cell(0, 0)
337
- shading_elm = parse_xml(f'<w:shd {nsdecls("w")} w:fill="E2EFDA"/>')
338
- cell._tc.get_or_add_tcPr().append(shading_elm)
339
-
340
- p = cell.paragraphs[0]
341
- run = p.add_run("NB2: Après le choix des catégories d'éléments gymniques par le candidat, ce dernier remplira la colonne de pointage selon l'orientation suivante: A (0.25; 0.5; 0.75; 1) B (0.25; 0.5; 0.75; 1; 1.25; 1.5) C (0.5; 0.75; 1; 1.25; 1.5; 2) D (0.75; 1; 1.25; 1.5; 2; 2.5) et E (0.75; 1; 1.5; 2; 2.5; 3) également, le candidat devra fournir 2 copies de son projet sur une page! (appréciations: NR, NM, PM, M).")
342
- run.italic = True
343
- run.font.size = Pt(8)
344
-
345
- def ajouter_lignes_correcteurs(self):
346
- para_intro = self.document.add_paragraph()
347
- para_intro.space_before = Pt(6)
348
-
349
- for role in ["Projet", "principal", "ROV"]:
350
- para = self.document.add_paragraph()
351
- para.space_before = Pt(4)
352
- para.space_after = Pt(4)
353
- run = para.add_run(f"Correcteur {role} : ")
354
- run.bold = True
355
- para.add_run(".................................................................")
356
-
357
- # Méthodes de modification des données
358
- def modifier_centre_examen(self, nom):
359
- self.centre_examen = nom
360
-
361
- def modifier_type_examen(self, type_examen):
362
- self.type_examen = type_examen
363
-
364
- def modifier_serie(self, serie):
365
- self.serie = serie
366
-
367
- def modifier_etablissement(self, nom):
368
- self.etablissement = nom
369
-
370
- def modifier_session(self, annee):
371
- self.session = annee
372
-
373
- def modifier_candidat(self, nom):
374
- self.nom_candidat = nom
375
-
376
- def ajouter_element(self, nom, categorie, points):
377
- self.elements_techniques.append({
378
- "nom": nom,
379
- "categorie": categorie,
380
- "points": float(points)
381
- })
382
-
383
- def generer_document(self, nom_fichier="evaluation_gymnastique.docx"):
384
- self.ajouter_entete_colore()
385
- self.creer_tableau_elements()
386
- self.ajouter_note_jury()
387
- self.creer_tableau_recapitulatif()
388
- self.ajouter_accolade()
389
- self.ajouter_zone_note()
390
- self.ajouter_note_candidat_avec_cadre()
391
- self.ajouter_lignes_correcteurs()
392
- self.document.save(nom_fichier)
393
- return nom_fichier
394
-
395
- # --- Application Flask ---
396
- app = Flask(__name__)
397
-
398
- @app.route("/", methods=["GET", "POST"])
399
- def index():
400
- if request.method == "POST":
401
- # Récupération des informations depuis le formulaire
402
- centre_examen = request.form.get("centre_examen", "Centre d'examen")
403
- type_examen = request.form.get("type_examen", "Bac Général")
404
- serie = request.form.get("serie", "Série")
405
- etablissement = request.form.get("etablissement", "Établissement")
406
- session_value = request.form.get("session", "2025")
407
- nom_candidat = request.form.get("nom_candidat", "Candidat")
408
-
409
- # Création et configuration du document
410
- evaluation = EvaluationGymnique()
411
- evaluation.modifier_centre_examen(centre_examen)
412
- evaluation.modifier_type_examen(type_examen)
413
- evaluation.modifier_serie(serie)
414
- evaluation.modifier_etablissement(etablissement)
415
- evaluation.modifier_session(session_value)
416
- evaluation.modifier_candidat(nom_candidat)
417
-
418
- # Récupération des éléments techniques ajoutés dynamiquement
419
- element_names = request.form.getlist("new_element_name")
420
- element_categories = request.form.getlist("new_element_categorie")
421
- element_points = request.form.getlist("new_element_points")
422
- for name, cat, pts in zip(element_names, element_categories, element_points):
423
- if name and cat and pts:
424
- evaluation.ajouter_element(name, cat, pts)
425
-
426
- # Génération du document DOCX
427
- filename = "evaluation_gymnastique.docx"
428
- evaluation.generer_document(filename)
429
-
430
- # Vérification du format de sortie demandé
431
- output_format = request.form.get("format", "docx")
432
- if output_format == "pdf":
433
- # Conversion en PDF via ConvertAPI
434
- result = convertapi.convert('pdf', {
435
- 'File': filename,
436
- 'FileName': 'evaluation_gymnastique',
437
- 'ConvertMetadata': 'false',
438
- 'ConvertHeadings': 'false'
439
- }, from_format='doc')
440
- pdf_filename = "evaluation_gymnastique.pdf"
441
- result.save_files(pdf_filename)
442
- return send_file(pdf_filename, as_attachment=True)
443
- else:
444
- return send_file(filename, as_attachment=True)
445
-
446
- return render_template("index.html")
447
-
448
- if __name__ == "__main__":
449
- app.run(debug=True)