Docfile commited on
Commit
f025ca4
·
verified ·
1 Parent(s): b0d762c

Delete templates/math.html

Browse files
Files changed (1) hide show
  1. templates/math.html +0 -535
templates/math.html DELETED
@@ -1,535 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="fr">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Mariam - Résolution de Problèmes Mathématiques</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <script defer src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script>
9
- <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
10
- <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
11
- <link rel="preconnect" href="https://fonts.googleapis.com">
12
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
13
- <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
14
- <style>
15
- body {
16
- font-family: 'Poppins', sans-serif;
17
- }
18
- .dropzone {
19
- border: 3px dashed #3b82f6; /* Increased border thickness */
20
- transition: all 0.3s ease;
21
- border-radius: 10px; /* More rounded corners */
22
- padding: 3rem; /* Increased padding */
23
- background-color: #f5f5f5; /* Lighter background color */
24
- }
25
-
26
- .dropzone:hover {
27
- border-color: #2563eb;
28
- background-color: rgba(59, 130, 246, 0.1);
29
- }
30
-
31
- .loading {
32
- display: none;
33
- }
34
-
35
- .loading.active {
36
- display: flex;
37
- }
38
-
39
- .math-content {
40
- font-size: 1.1em;
41
- line-height: 1.6;
42
- overflow-x: auto;
43
- }
44
-
45
- .math-content p {
46
- margin-bottom: 1rem;
47
- white-space: pre-wrap;
48
- }
49
-
50
- .math-content .MathJax {
51
- overflow-x: auto;
52
- overflow-y: hidden;
53
- padding: 0.5rem 0;
54
- }
55
-
56
- @media (max-width: 640px) {
57
- .math-content .MathJax {
58
- font-size: 0.9em;
59
- }
60
- }
61
-
62
- .math-hidden {
63
- visibility: hidden;
64
- }
65
-
66
- .saved-response-header {
67
- cursor: pointer;
68
- display: flex;
69
- justify-content: space-between;
70
- align-items: center;
71
- padding: 0.75rem 1rem;
72
- background-color: #e5e7eb; /* Changed background color */
73
- border-bottom: 1px solid #d1d5db; /* Changed border color */
74
- border-radius: 8px; /* Added border-radius */
75
- font-weight: 500; /* Added font weight */
76
- }
77
-
78
- .saved-response-content {
79
- padding: 1rem;
80
- display: none;
81
- border-radius: 8px; /* Added border-radius */
82
- }
83
-
84
- .saved-response-item.open .saved-response-content {
85
- display: block;
86
- }
87
- /* Custom button style */
88
- .btn {
89
- padding: 0.75rem 1.5rem;
90
- border-radius: 0.5rem;
91
- font-weight: 600;
92
- transition: all 0.3s ease;
93
- }
94
-
95
- .btn-primary {
96
- background-color: #3b82f6;
97
- color: #fff;
98
- }
99
-
100
- .btn-primary:hover {
101
- background-color: #2563eb;
102
- }
103
-
104
- .btn-danger {
105
- background-color: #ef4444;
106
- color: #fff;
107
- }
108
-
109
- .btn-danger:hover {
110
- background-color: #dc2626;
111
- }
112
-
113
- /* Custom select style */
114
- .select {
115
- border: 1px solid #d1d5db;
116
- border-radius: 0.5rem;
117
- padding: 0.75rem 1rem;
118
- appearance: none;
119
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
120
- background-repeat: no-repeat;
121
- background-position: right 0.75rem center;
122
- background-size: 1em;
123
- padding-right: 2.5rem;
124
- }
125
-
126
- .select:focus {
127
- outline: none;
128
- box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.5);
129
- }
130
- </style>
131
- <script>
132
- window.MathJax = {
133
- tex: {
134
- inlineMath: [['$', '$'], ['\\(', '\\)']],
135
- displayMath: [['$$', '$$'], ['\\[', '\\]']],
136
- processEscapes: true,
137
- macros: {
138
- R: "{\\mathbb{R}}",
139
- N: "{\\mathbb{N}}",
140
- Z: "{\\mathbb{Z}}",
141
- vecv: ["\\begin{pmatrix}#1\\\\#2\\\\#3\\end{pmatrix}", 3]
142
- }
143
- },
144
- svg: {
145
- fontCache: 'global'
146
- },
147
- startup: {
148
- pageReady: () => {
149
- return Promise.resolve();
150
- }
151
- },
152
- options: {
153
- renderActions: {
154
- addMenu: [],
155
- checkLoading: [150, () => {
156
- document.querySelectorAll('.math-content').forEach(el => {
157
- el.classList.remove('math-hidden');
158
- });
159
- }]
160
- }
161
- }
162
- };
163
- </script>
164
- <script>
165
- function loadMathJax() {
166
- return new Promise((resolve, reject) => {
167
- const script = document.createElement('script');
168
- script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js';
169
- script.async = true;
170
- script.id = 'MathJax-script';
171
- script.onload = resolve;
172
- script.onerror = reject;
173
- document.head.appendChild(script);
174
- });
175
- }
176
- loadMathJax().catch(console.error);
177
- </script>
178
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/localforage.min.js"></script>
179
- </head>
180
-
181
- <body class="bg-gray-100">
182
- <div class="container mx-auto px-4 py-8 max-w-4xl">
183
- <header class="text-center mb-12">
184
- <h1 class="text-4xl font-bold text-blue-600 mb-4">
185
- <span class="bg-gradient-to-r from-blue-500 to-blue-700 text-transparent bg-clip-text">Mariam</span>
186
- - Résolution de Problèmes Mathématiques
187
- </h1>
188
- <p class="text-gray-500 text-lg">Votre assistant intelligent pour des solutions mathématiques détaillées</p>
189
- </header>
190
- <div class="mb-8">
191
- <form id="uploadForm" class="space-y-4">
192
- <div id="dropzone"
193
- class="dropzone rounded-lg text-center cursor-pointer shadow-md hover:shadow-lg transition-all">
194
- <input type="file" id="fileInput" class="hidden" accept="image/*">
195
- <div class="flex flex-col items-center space-y-4">
196
- <i class="fas fa-cloud-upload-alt text-6xl text-blue-500"></i>
197
- <div class="text-lg text-gray-600">
198
- Glissez votre image ici ou <span class="text-blue-500 font-semibold">cliquez pour
199
- sélectionner</span>
200
- </div>
201
- <p class="text-sm text-gray-500">Formats acceptés: PNG, JPG, JPEG</p>
202
- </div>
203
- </div>
204
-
205
- <div class="space-y-4">
206
- <label for="customInstruction" class="block text-gray-600 font-medium">Instruction
207
- personnalisée (optionnel)</label>
208
- <input type="text" id="customInstruction" name="custom_instruction"
209
- class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
210
- placeholder="Exemple : Résoudre en utilisant le théorème de Pythagore">
211
- </div>
212
-
213
- <div class="flex flex-col md:flex-row justify-center items-center space-y-4 md:space-y-0 md:space-x-4">
214
- <select id="modelChoice" name="model_choice"
215
- class="select w-full md:w-auto">
216
- <option value="mariam's">Mariam's (Ultra performant)</option>
217
- <option value="qwen2">Qwen2 (lent et performant)</option>
218
- </select>
219
- <button type="submit"
220
- class="btn btn-primary w-full md:w-auto flex items-center space-x-2 disabled:opacity-50 disabled:cursor-not-allowed">
221
- <i class="fas fa-paper-plane"></i>
222
- <span>Analyser l'image</span>
223
- </button>
224
- </div>
225
- </form>
226
- </div>
227
-
228
- <div id="loading" class="loading flex-col items-center justify-center space-y-4 my-8">
229
- <div class="animate-spin rounded-full h-16 w-16 border-t-4 border-b-4 border-blue-500"></div>
230
- <p class="text-gray-600 font-medium text-lg">Analyse en cours...</p>
231
- </div>
232
-
233
- <div id="response" class="hidden">
234
- <div class="bg-white rounded-xl shadow-lg p-6 mb-8">
235
- <h2 id="modelUsed" class="text-2xl font-semibold text-blue-600 mb-4">Solution (Modèle: <span
236
- id="modelName"></span>)</h2>
237
- <div id="latexContent" class="prose max-w-none math-content math-hidden"></div>
238
- </div>
239
- </div>
240
-
241
- <div id="savedResponsesSection" class="mt-8">
242
- <div class="flex justify-between items-center mb-4">
243
- <h2 class="text-2xl font-semibold text-blue-600">Réponses Sauvegardées</h2>
244
- <button id="clearSavedResponses"
245
- class="btn btn-danger">
246
- <i class="fas fa-trash-alt"></i> Effacer Tout
247
- </button>
248
- </div>
249
- <div id="savedResponses" class="space-y-4"></div>
250
- </div>
251
-
252
- <div id="errorMessage"
253
- class="hidden bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-lg relative my-4" role="alert">
254
- <strong class="font-bold">Erreur!</strong>
255
- <span class="block sm:inline" id="errorText"></span>
256
- </div>
257
- </div>
258
-
259
- <script>
260
- // JavaScript code (same as before, but with minor adjustments if needed)
261
- document.addEventListener('DOMContentLoaded', function () {
262
- const dropzone = document.getElementById('dropzone');
263
- const fileInput = document.getElementById('fileInput');
264
- const uploadForm = document.getElementById('uploadForm');
265
- const loading = document.getElementById('loading');
266
- const response = document.getElementById('response');
267
- const latexContent = document.getElementById('latexContent');
268
- const errorMessage = document.getElementById('errorMessage');
269
- const errorText = document.getElementById('errorText');
270
- const submitButton = uploadForm.querySelector('button[type="submit"]');
271
- const savedResponsesContainer = document.getElementById('savedResponses');
272
- const clearSavedResponsesButton = document.getElementById('clearSavedResponses');
273
- const modelChoiceSelect = document.getElementById('modelChoice');
274
- const modelNameSpan = document.getElementById('modelName');
275
- const customInstructionInput = document.getElementById('customInstruction');
276
-
277
- let mathJaxReady = false;
278
- window.MathJax.startup.promise.then(() => {
279
- mathJaxReady = true;
280
- });
281
-
282
- marked.setOptions({
283
- breaks: true,
284
- gfm: true,
285
- pedantic: false,
286
- smartLists: true
287
- });
288
-
289
- function showError(message) {
290
- errorText.textContent = message;
291
- errorMessage.classList.remove('hidden');
292
- setTimeout(() => {
293
- errorMessage.classList.add('hidden');
294
- }, 5000);
295
- }
296
-
297
- async function renderMathContent(text) {
298
- try {
299
- if (!mathJaxReady) {
300
- await window.MathJax.startup.promise;
301
- }
302
- latexContent.innerHTML = '';
303
- latexContent.classList.add('math-hidden');
304
- const htmlContent = marked.parse(text);
305
- latexContent.innerHTML = htmlContent;
306
- await MathJax.typesetPromise([latexContent]);
307
- response.classList.remove('hidden');
308
- latexContent.classList.remove('math-hidden');
309
- } catch (error) {
310
- console.error('Erreur lors du rendu:', error);
311
- showError('Erreur lors du rendu de la formule mathématique');
312
- latexContent.innerHTML = `
313
- <div class="text-red-600 mb-4">Une erreur s'est produite lors du rendu. Voici le texte brut :</div>
314
- <pre class="bg-gray-100 p-4 rounded-lg overflow-x-auto">${text}</pre>
315
- `;
316
- latexContent.classList.remove('math-hidden');
317
- }
318
- }
319
-
320
- function handleDragOver(e) {
321
- e.preventDefault();
322
- e.stopPropagation();
323
- dropzone.classList.add('bg-blue-50');
324
- }
325
-
326
- function handleDragLeave(e) {
327
- e.preventDefault();
328
- e.stopPropagation();
329
- dropzone.classList.remove('bg-blue-50');
330
- }
331
-
332
- function handleDrop(e) {
333
- e.preventDefault();
334
- e.stopPropagation();
335
- dropzone.classList.remove('bg-blue-50');
336
- const files = e.dataTransfer.files;
337
- if (files.length > 0 && files[0].type.startsWith('image/')) {
338
- fileInput.files = files;
339
- handleFileSelect(files[0]);
340
- } else {
341
- showError('Veuillez déposer une image valide');
342
- }
343
- }
344
-
345
- function handleFileSelect(file) {
346
- if (file && file.type.startsWith('image/')) {
347
- const reader = new FileReader();
348
- reader.onload = function (e) {
349
- const preview = document.createElement('img');
350
- preview.src = e.target.result;
351
- preview.classList.add('max-h-48', 'mx-auto', 'mt-4', 'rounded-lg');
352
- const oldPreview = dropzone.querySelector('img');
353
- if (oldPreview) oldPreview.remove();
354
- dropzone.appendChild(preview);
355
- submitButton.disabled = false;
356
- };
357
- reader.readAsDataURL(file);
358
- } else {
359
- showError('Veuillez sélectionner une image valide');
360
- }
361
- }
362
-
363
- dropzone.addEventListener('dragover', handleDragOver);
364
- dropzone.addEventListener('dragleave', handleDragLeave);
365
- dropzone.addEventListener('drop', handleDrop);
366
- dropzone.addEventListener('click', () => fileInput.click());
367
-
368
- fileInput.addEventListener('change', (e) => {
369
- if (e.target.files.length > 0) {
370
- handleFileSelect(e.target.files[0]);
371
- }
372
- });
373
-
374
- async function saveResponse(response, model) {
375
- const timestamp = new Date().getTime();
376
- const key = `response-${timestamp}-${model}`;
377
- try {
378
- await localforage.setItem(key, response);
379
- loadSavedResponses();
380
- } catch (error) {
381
- console.error('Erreur lors de la sauvegarde:', error);
382
- showError('Erreur lors de la sauvegarde de la réponse en local');
383
- }
384
- }
385
-
386
- async function clearSavedResponses() {
387
- Swal.fire({
388
- title: 'Êtes-vous sûr?',
389
- text: "Vous ne pourrez pas revenir en arrière!",
390
- icon: 'warning',
391
- showCancelButton: true,
392
- confirmButtonColor: '#d33',
393
- cancelButtonColor: '#3085d6',
394
- confirmButtonText: 'Oui, effacer!',
395
- cancelButtonText: 'Annuler'
396
- }).then(async (result) => {
397
- if (result.isConfirmed) {
398
- try {
399
- await localforage.clear();
400
- console.log('Réponses sauvegardées effacées');
401
- loadSavedResponses();
402
- Swal.fire('Effacé!', 'Les réponses ont été supprimées.', 'success');
403
- } catch (error) {
404
- console.error("Erreur lors de l'effacement des réponses sauvegardées:",
405
- error);
406
- showError("Erreur lors de l'effacement des réponses sauvegardées");
407
- Swal.fire('Erreur!', 'Une erreur est survenue lors de la suppression.',
408
- 'error');
409
- }
410
- }
411
- });
412
- }
413
-
414
- async function loadSavedResponses() {
415
- try {
416
- savedResponsesContainer.innerHTML = '';
417
- const keys = await localforage.keys();
418
- keys.sort((a, b) => parseInt(b.replace('response-', '').split('-')[0]) - parseInt(a
419
- .replace('response-', '').split('-')[0]));
420
-
421
- for (const key of keys) {
422
- const response = await localforage.getItem(key);
423
- const [, timestamp, model] = key.split('-');
424
- const responseItem = document.createElement('div');
425
- responseItem.className =
426
- 'saved-response-item bg-gray-100 rounded-lg shadow-md overflow-hidden';
427
-
428
- const header = document.createElement('div');
429
- header.className = 'saved-response-header';
430
- header.innerHTML = `
431
- <span class="text-blue-600 font-medium">Réponse du ${new Date(parseInt(timestamp)).toLocaleString()} (Modèle: ${model})</span>
432
- <div>
433
- <button class="toggle-content px-2 py-1 rounded-md text-xs bg-blue-500 hover:bg-blue-700 text-white mr-1"><i class="fas fa-chevron-down"></i></button>
434
- <button class="delete-response px-2 py-1 rounded-md text-xs bg-red-500 hover:bg-red-700 text-white"><i class="fas fa-trash-alt"></i></button>
435
- </div>
436
- `;
437
- responseItem.appendChild(header);
438
-
439
- const content = document.createElement('div');
440
- content.className = 'saved-response-content math-content math-hidden';
441
- content.innerHTML = marked.parse(response);
442
- responseItem.appendChild(content);
443
- savedResponsesContainer.appendChild(responseItem);
444
-
445
- header.querySelector('.toggle-content').addEventListener('click', () => {
446
- responseItem.classList.toggle('open');
447
- header.querySelector('i').classList.toggle('fa-chevron-down');
448
- header.querySelector('i').classList.toggle('fa-chevron-up');
449
- MathJax.typesetPromise([content]);
450
- content.classList.remove('math-hidden');
451
- });
452
-
453
- header.querySelector('.delete-response').addEventListener('click', async () => {
454
- try {
455
- await localforage.removeItem(key);
456
- responseItem.remove();
457
- } catch (error) {
458
- console.error('Erreur lors de la suppression de la réponse:',
459
- error);
460
- showError('Erreur lors de la suppression de la réponse');
461
- }
462
- });
463
-
464
- MathJax.typesetPromise([content]);
465
- content.classList.remove('math-hidden');
466
- }
467
- } catch (error) {
468
- console.error('Erreur lors du chargement des réponses sauvegardées:', error);
469
- showError('Erreur lors du chargement des réponses sauvegardées');
470
- }
471
- }
472
-
473
- uploadForm.addEventListener('submit', async (e) => {
474
- e.preventDefault();
475
-
476
- if (!fileInput.files.length) {
477
- showError('Veuillez sélectionner une image');
478
- return;
479
- }
480
-
481
- const formData = new FormData();
482
- formData.append('image', fileInput.files[0]);
483
- formData.append('model_choice', modelChoiceSelect.value);
484
- formData.append('custom_instruction', customInstructionInput.value);
485
-
486
- try {
487
- submitButton.disabled = true;
488
- loading.classList.add('active');
489
- response.classList.add('hidden');
490
- errorMessage.classList.add('hidden');
491
-
492
- const res = await fetch('/upload', {
493
- method: 'POST',
494
- body: formData
495
- });
496
-
497
- const data = await res.json();
498
-
499
- if (data.error) {
500
- throw new Error(data.error);
501
- }
502
-
503
- await renderMathContent(data.result);
504
- modelNameSpan.textContent = data.model;
505
- saveResponse(data.result, data.model);
506
-
507
- // Afficher les graphiques générés
508
- if (data.image_paths) {
509
- const imageContainer = document.createElement('div');
510
- imageContainer.className = 'mt-4';
511
- data.image_paths.forEach(imagePath => {
512
- const img = document.createElement('img');
513
- img.src = `/temp/${imagePath.split('/').pop()}`;
514
- img.className = 'max-w-full h-auto mt-2 rounded-lg';
515
- imageContainer.appendChild(img);
516
- });
517
- latexContent.appendChild(imageContainer);
518
- }
519
-
520
- } catch (error) {
521
- console.error('Erreur:', error);
522
- showError(error.message || 'Une erreur est survenue lors du traitement');
523
- } finally {
524
- loading.classList.remove('active');
525
- submitButton.disabled = false;
526
- }
527
- });
528
-
529
- loadSavedResponses();
530
- clearSavedResponsesButton.addEventListener('click', clearSavedResponses);
531
- });
532
- </script>
533
- </body>
534
-
535
- </html>