Adam77 commited on
Commit
4e9ed4e
·
verified ·
1 Parent(s): 992e934

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +732 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Aide Aux Devoirs
3
- emoji:
4
  colorFrom: gray
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: aide-aux-devoirs
3
+ emoji: 🐳
4
  colorFrom: gray
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,732 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Aide aux devoirs Maths/Physique/Chimie</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .mind-map {
11
+ min-height: 500px;
12
+ background-color: #f8fafc;
13
+ border-radius: 1rem;
14
+ position: relative;
15
+ overflow: hidden;
16
+ }
17
+ .node {
18
+ position: absolute;
19
+ padding: 1rem;
20
+ border-radius: 0.5rem;
21
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
22
+ cursor: move;
23
+ transition: all 0.2s;
24
+ max-width: 250px;
25
+ min-width: 150px;
26
+ }
27
+ .node:hover {
28
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
29
+ transform: scale(1.02);
30
+ }
31
+ .node-main {
32
+ background-color: #3b82f6;
33
+ color: white;
34
+ font-weight: bold;
35
+ z-index: 10;
36
+ }
37
+ .node-question {
38
+ background-color: #f59e0b;
39
+ color: white;
40
+ z-index: 5;
41
+ }
42
+ .node-answer {
43
+ background-color: #10b981;
44
+ color: white;
45
+ z-index: 3;
46
+ }
47
+ .node-blank {
48
+ background-color: white;
49
+ border: 2px dashed #64748b;
50
+ color: #334155;
51
+ }
52
+ .connector {
53
+ position: absolute;
54
+ background-color: #94a3b8;
55
+ height: 2px;
56
+ transform-origin: left center;
57
+ z-index: 1;
58
+ }
59
+ .blank-input {
60
+ background-color: transparent;
61
+ border-bottom: 2px solid #3b82f6;
62
+ color: #3b82f6;
63
+ font-weight: bold;
64
+ width: 80px;
65
+ text-align: center;
66
+ margin: 0 5px;
67
+ }
68
+ .blank-input:focus {
69
+ outline: none;
70
+ border-bottom-color: #1d4ed8;
71
+ }
72
+ .subject-tab.active {
73
+ background-color: #3b82f6;
74
+ color: white;
75
+ }
76
+ .level-tab.active {
77
+ background-color: #10b981;
78
+ color: white;
79
+ }
80
+ </style>
81
+ </head>
82
+ <body class="bg-gray-50 min-h-screen">
83
+ <div class="container mx-auto px-4 py-8">
84
+ <header class="mb-8 text-center">
85
+ <h1 class="text-4xl font-bold text-blue-600 mb-2">Aide aux Devoirs</h1>
86
+ <h2 class="text-2xl text-gray-700">Mathématiques • Physique • Chimie</h2>
87
+ <p class="text-gray-500 mt-2">De la 2nde à la Terminale</p>
88
+ </header>
89
+
90
+ <div class="flex flex-col lg:flex-row gap-6">
91
+ <!-- Sidebar -->
92
+ <div class="w-full lg:w-1/4 bg-white p-6 rounded-xl shadow-md">
93
+ <div class="mb-6">
94
+ <h3 class="text-lg font-semibold mb-3 text-gray-800">Matières</h3>
95
+ <div class="grid grid-cols-3 gap-2">
96
+ <button class="subject-tab active py-2 px-3 rounded-lg transition" data-subject="maths">
97
+ <i class="fas fa-square-root-alt mr-2"></i> Maths
98
+ </button>
99
+ <button class="subject-tab py-2 px-3 rounded-lg transition" data-subject="physics">
100
+ <i class="fas fa-atom mr-2"></i> Physique
101
+ </button>
102
+ <button class="subject-tab py-2 px-3 rounded-lg transition" data-subject="chemistry">
103
+ <i class="fas fa-flask mr-2"></i> Chimie
104
+ </button>
105
+ </div>
106
+ </div>
107
+
108
+ <div class="mb-6">
109
+ <h3 class="text-lg font-semibold mb-3 text-gray-800">Niveau</h3>
110
+ <div class="grid grid-cols-3 gap-2">
111
+ <button class="level-tab py-2 px-3 rounded-lg transition" data-level="2nde">
112
+ 2nde
113
+ </button>
114
+ <button class="level-tab py-2 px-3 rounded-lg transition active" data-level="1ere">
115
+ 1ère
116
+ </button>
117
+ <button class="level-tab py-2 px-3 rounded-lg transition" data-level="terminale">
118
+ Terminale
119
+ </button>
120
+ </div>
121
+ </div>
122
+
123
+ <div class="mb-6">
124
+ <h3 class="text-lg font-semibold mb-3 text-gray-800">Thèmes</h3>
125
+ <div class="space-y-2" id="themes-container">
126
+ <!-- Thèmes seront chargés dynamiquement -->
127
+ </div>
128
+ </div>
129
+
130
+ <div class="mb-6">
131
+ <h3 class="text-lg font-semibold mb-3 text-gray-800">Outils</h3>
132
+ <button id="add-question" class="w-full bg-yellow-500 hover:bg-yellow-600 text-white py-2 px-4 rounded-lg mb-2 transition flex items-center justify-center">
133
+ <i class="fas fa-question-circle mr-2"></i> Ajouter Question
134
+ </button>
135
+ <button id="add-answer" class="w-full bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded-lg mb-2 transition flex items-center justify-center">
136
+ <i class="fas fa-lightbulb mr-2"></i> Ajouter Réponse
137
+ </button>
138
+ <button id="add-blank" class="w-full bg-white border border-blue-500 text-blue-500 hover:bg-blue-50 py-2 px-4 rounded-lg transition flex items-center justify-center">
139
+ <i class="fas fa-edit mr-2"></i> Ajouter Trou
140
+ </button>
141
+ </div>
142
+
143
+ <div class="bg-blue-50 p-4 rounded-lg border border-blue-200">
144
+ <h4 class="font-medium text-blue-800 mb-2 flex items-center">
145
+ <i class="fas fa-info-circle mr-2"></i> Comment utiliser
146
+ </h4>
147
+ <p class="text-sm text-blue-700">
148
+ 1. Sélectionnez une matière et un niveau<br>
149
+ 2. Choisissez un thème<br>
150
+ 3. Explorez les questions et réponses<br>
151
+ 4. Complétez les trous pour vérifier vos connaissances
152
+ </p>
153
+ </div>
154
+ </div>
155
+
156
+ <!-- Main content -->
157
+ <div class="w-full lg:w-3/4">
158
+ <div class="bg-white p-6 rounded-xl shadow-md mb-6">
159
+ <div class="flex justify-between items-center mb-4">
160
+ <h3 class="text-xl font-semibold text-gray-800" id="current-theme">Sélectionnez un thème</h3>
161
+ <div class="flex space-x-2">
162
+ <button id="zoom-in" class="bg-gray-200 hover:bg-gray-300 p-2 rounded-lg">
163
+ <i class="fas fa-search-plus"></i>
164
+ </button>
165
+ <button id="zoom-out" class="bg-gray-200 hover:bg-gray-300 p-2 rounded-lg">
166
+ <i class="fas fa-search-minus"></i>
167
+ </button>
168
+ <button id="reset-view" class="bg-gray-200 hover:bg-gray-300 p-2 rounded-lg">
169
+ <i class="fas fa-expand"></i>
170
+ </button>
171
+ </div>
172
+ </div>
173
+
174
+ <div class="mind-map relative" id="mind-map">
175
+ <!-- Mind map content will be generated here -->
176
+ <div class="node node-main absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2" style="transform: translate(-50%, -50%);">
177
+ <div class="text-center">
178
+ <i class="fas fa-brain text-2xl mb-2"></i>
179
+ <div>Commencez par sélectionner un thème</div>
180
+ </div>
181
+ </div>
182
+ </div>
183
+ </div>
184
+
185
+ <div class="bg-white p-6 rounded-xl shadow-md">
186
+ <h3 class="text-xl font-semibold text-gray-800 mb-4">Vérifiez vos réponses</h3>
187
+ <div class="flex flex-wrap gap-4" id="blanks-container">
188
+ <!-- Blank answers will appear here -->
189
+ <div class="bg-gray-100 p-4 rounded-lg text-center w-full">
190
+ <p class="text-gray-500">Les trous que vous complétez apparaîtront ici pour vérification.</p>
191
+ </div>
192
+ </div>
193
+ <button id="check-answers" class="mt-4 bg-blue-600 hover:bg-blue-700 text-white py-2 px-6 rounded-lg transition hidden">
194
+ <i class="fas fa-check-circle mr-2"></i> Vérifier les réponses
195
+ </button>
196
+ </div>
197
+ </div>
198
+ </div>
199
+ </div>
200
+
201
+ <script>
202
+ // Sample data for questions and answers
203
+ const data = {
204
+ maths: {
205
+ '2nde': {
206
+ 'Fonctions': [
207
+ {
208
+ question: "Quelle est la définition d'une fonction ?",
209
+ answer: "Une fonction est une relation qui �� chaque élément d'un ensemble de départ associe au plus un élément d'un ensemble d'arrivée."
210
+ },
211
+ {
212
+ question: "Comment calcule-t-on l'image d'un nombre par une fonction f ?",
213
+ answer: "On remplace x par le nombre dans l'expression de f(x)."
214
+ },
215
+ {
216
+ question: "Qu'est-ce qu'un antécédent ?",
217
+ answer: "Un antécédent d'un nombre y par une fonction f est un nombre x tel que f(x) = y."
218
+ }
219
+ ],
220
+ 'Géométrie': [
221
+ {
222
+ question: "Quelle est la formule du théorème de Pythagore ?",
223
+ answer: "Dans un triangle rectangle, si a et b sont les longueurs des côtés de l'angle droit et c celle de l'hypoténuse, alors a² + b² = c²."
224
+ }
225
+ ]
226
+ },
227
+ '1ere': {
228
+ 'Dérivation': [
229
+ {
230
+ question: "Quelle est la dérivée de f(x) = x² ?",
231
+ answer: "f'(x) = 2x"
232
+ },
233
+ {
234
+ question: "Que représente f'(a) graphiquement ?",
235
+ answer: "C'est le coefficient directeur de la tangente à la courbe de f au point d'abscisse a."
236
+ }
237
+ ],
238
+ 'Probabilités': [
239
+ {
240
+ question: "Comment calcule-t-on la probabilité de A sachant B ?",
241
+ answer: "P(A|B) = P(A∩B) / P(B)"
242
+ }
243
+ ]
244
+ },
245
+ 'terminale': {
246
+ 'Limites': [
247
+ {
248
+ question: "Que signifie lim f(x) = +∞ quand x→+∞ ?",
249
+ answer: "La fonction f prend des valeurs aussi grandes qu'on veut dès que x est suffisamment grand."
250
+ }
251
+ ],
252
+ 'Exponentielle': [
253
+ {
254
+ question: "Quelle est la dérivée de exp(x) ?",
255
+ answer: "exp(x) (la fonction exponentielle est sa propre dérivée)"
256
+ }
257
+ ]
258
+ }
259
+ },
260
+ physics: {
261
+ '2nde': {
262
+ 'Mouvement': [
263
+ {
264
+ question: "Comment calcule-t-on la vitesse moyenne ?",
265
+ answer: "v = distance parcourue / durée du parcours"
266
+ }
267
+ ]
268
+ },
269
+ '1ere': {
270
+ 'Ondes': [
271
+ {
272
+ question: "Quelle est la relation entre longueur d'onde, fréquence et célérité ?",
273
+ answer: "λ = v / f où λ est la longueur d'onde, v la célérité et f la fréquence."
274
+ }
275
+ ]
276
+ },
277
+ 'terminale': {
278
+ 'Mécanique': [
279
+ {
280
+ question: "Énoncez la 2ème loi de Newton",
281
+ answer: "ΣF = m·a (la somme des forces est égale à la masse fois l'accélération)"
282
+ }
283
+ ]
284
+ }
285
+ },
286
+ chemistry: {
287
+ '2nde': {
288
+ 'Atome': [
289
+ {
290
+ question: "Quels sont les 3 constituants principaux d'un atome ?",
291
+ answer: "Protons, neutrons et électrons"
292
+ }
293
+ ]
294
+ },
295
+ '1ere': {
296
+ 'Transformations': [
297
+ {
298
+ question: "Qu'est-ce qu'une réaction d'oxydoréduction ?",
299
+ answer: "Une réaction où il y a transfert d'électrons entre espèces chimiques."
300
+ }
301
+ ]
302
+ },
303
+ 'terminale': {
304
+ 'Cinétique': [
305
+ {
306
+ question: "Quels facteurs influencent la vitesse d'une réaction chimique ?",
307
+ answer: "Température, concentration, catalyseur, état de division des réactifs"
308
+ }
309
+ ]
310
+ }
311
+ }
312
+ };
313
+
314
+ // Current selections
315
+ let currentSubject = 'maths';
316
+ let currentLevel = '1ere';
317
+ let currentTheme = '';
318
+ let nodes = [];
319
+ let connectors = [];
320
+ let blanks = [];
321
+ let scale = 1;
322
+
323
+ // DOM elements
324
+ const mindMap = document.getElementById('mind-map');
325
+ const themesContainer = document.getElementById('themes-container');
326
+ const currentThemeDisplay = document.getElementById('current-theme');
327
+ const blanksContainer = document.getElementById('blanks-container');
328
+ const checkAnswersBtn = document.getElementById('check-answers');
329
+
330
+ // Initialize
331
+ document.addEventListener('DOMContentLoaded', () => {
332
+ // Set up event listeners
333
+ setupEventListeners();
334
+
335
+ // Load initial data
336
+ updateThemeList();
337
+ });
338
+
339
+ function setupEventListeners() {
340
+ // Subject tabs
341
+ document.querySelectorAll('.subject-tab').forEach(tab => {
342
+ tab.addEventListener('click', () => {
343
+ document.querySelectorAll('.subject-tab').forEach(t => t.classList.remove('active'));
344
+ tab.classList.add('active');
345
+ currentSubject = tab.dataset.subject;
346
+ updateThemeList();
347
+ });
348
+ });
349
+
350
+ // Level tabs
351
+ document.querySelectorAll('.level-tab').forEach(tab => {
352
+ tab.addEventListener('click', () => {
353
+ document.querySelectorAll('.level-tab').forEach(t => t.classList.remove('active'));
354
+ tab.classList.add('active');
355
+ currentLevel = tab.dataset.level;
356
+ updateThemeList();
357
+ });
358
+ });
359
+
360
+ // Tool buttons
361
+ document.getElementById('add-question').addEventListener('click', addQuestionNode);
362
+ document.getElementById('add-answer').addEventListener('click', addAnswerNode);
363
+ document.getElementById('add-blank').addEventListener('click', addBlankNode);
364
+ document.getElementById('check-answers').addEventListener('click', checkAnswers);
365
+
366
+ // Zoom controls
367
+ document.getElementById('zoom-in').addEventListener('click', () => {
368
+ scale += 0.1;
369
+ updateZoom();
370
+ });
371
+
372
+ document.getElementById('zoom-out').addEventListener('click', () => {
373
+ if (scale > 0.5) {
374
+ scale -= 0.1;
375
+ updateZoom();
376
+ }
377
+ });
378
+
379
+ document.getElementById('reset-view').addEventListener('click', () => {
380
+ scale = 1;
381
+ updateZoom();
382
+ });
383
+ }
384
+
385
+ function updateZoom() {
386
+ mindMap.style.transform = `scale(${scale})`;
387
+ }
388
+
389
+ function updateThemeList() {
390
+ themesContainer.innerHTML = '';
391
+
392
+ const themes = data[currentSubject][currentLevel];
393
+ if (!themes) return;
394
+
395
+ Object.keys(themes).forEach(theme => {
396
+ const button = document.createElement('button');
397
+ button.className = 'w-full text-left py-2 px-3 rounded-lg hover:bg-gray-100 transition';
398
+ button.textContent = theme;
399
+ button.addEventListener('click', () => {
400
+ currentTheme = theme;
401
+ currentThemeDisplay.textContent = theme;
402
+ loadThemeContent();
403
+ });
404
+ themesContainer.appendChild(button);
405
+ });
406
+ }
407
+
408
+ function loadThemeContent() {
409
+ // Clear existing content
410
+ clearMindMap();
411
+
412
+ // Get questions for current theme
413
+ const questions = data[currentSubject][currentLevel][currentTheme];
414
+ if (!questions || questions.length === 0) return;
415
+
416
+ // Create main theme node
417
+ const mainNode = createNode(currentTheme, 'node-main', mindMap.offsetWidth / 2, mindMap.offsetHeight / 2);
418
+ nodes.push(mainNode);
419
+
420
+ // Create question nodes around the main node
421
+ const angleStep = (2 * Math.PI) / questions.length;
422
+ const radius = 150;
423
+
424
+ questions.forEach((q, i) => {
425
+ const angle = i * angleStep;
426
+ const x = mainNode.offsetLeft + mainNode.offsetWidth / 2 + Math.cos(angle) * radius - 100;
427
+ const y = mainNode.offsetTop + mainNode.offsetHeight / 2 + Math.sin(angle) * radius - 50;
428
+
429
+ const questionNode = createNode(q.question, 'node-question', x, y);
430
+ nodes.push(questionNode);
431
+
432
+ // Create answer node
433
+ const answerX = x + (Math.cos(angle) * 120);
434
+ const answerY = y + (Math.sin(angle) * 120);
435
+ const answerNode = createNode(q.answer, 'node-answer', answerX, answerY);
436
+ nodes.push(answerNode);
437
+
438
+ // Create connectors
439
+ createConnector(mainNode, questionNode);
440
+ createConnector(questionNode, answerNode);
441
+
442
+ // Add some blanks randomly
443
+ if (Math.random() > 0.7) {
444
+ addBlankToNode(answerNode);
445
+ }
446
+ });
447
+
448
+ // Make nodes draggable
449
+ makeNodesDraggable();
450
+ }
451
+
452
+ function clearMindMap() {
453
+ // Remove all nodes and connectors
454
+ nodes.forEach(node => node.remove());
455
+ connectors.forEach(connector => connector.remove());
456
+ blanks = [];
457
+ nodes = [];
458
+ connectors = [];
459
+
460
+ // Clear blanks container
461
+ blanksContainer.innerHTML = `
462
+ <div class="bg-gray-100 p-4 rounded-lg text-center w-full">
463
+ <p class="text-gray-500">Les trous que vous complétez apparaîtront ici pour vérification.</p>
464
+ </div>
465
+ `;
466
+ checkAnswersBtn.classList.add('hidden');
467
+ }
468
+
469
+ function createNode(content, className, x, y) {
470
+ const node = document.createElement('div');
471
+ node.className = `node ${className}`;
472
+ node.style.left = `${x}px`;
473
+ node.style.top = `${y}px`;
474
+ node.innerHTML = content;
475
+ mindMap.appendChild(node);
476
+ return node;
477
+ }
478
+
479
+ function createConnector(node1, node2) {
480
+ const connector = document.createElement('div');
481
+ connector.className = 'connector';
482
+
483
+ // Calculate position and dimensions
484
+ updateConnectorPosition(connector, node1, node2);
485
+
486
+ mindMap.appendChild(connector);
487
+ connectors.push(connector);
488
+ return connector;
489
+ }
490
+
491
+ function updateConnectorPosition(connector, node1, node2) {
492
+ const x1 = node1.offsetLeft + node1.offsetWidth / 2;
493
+ const y1 = node1.offsetTop + node1.offsetHeight / 2;
494
+ const x2 = node2.offsetLeft + node2.offsetWidth / 2;
495
+ const y2 = node2.offsetTop + node2.offsetHeight / 2;
496
+
497
+ const length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
498
+ const angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
499
+
500
+ connector.style.width = `${length}px`;
501
+ connector.style.left = `${x1}px`;
502
+ connector.style.top = `${y1}px`;
503
+ connector.style.transform = `rotate(${angle}deg)`;
504
+ }
505
+
506
+ function makeNodesDraggable() {
507
+ nodes.forEach(node => {
508
+ let isDragging = false;
509
+ let offsetX, offsetY;
510
+
511
+ node.addEventListener('mousedown', (e) => {
512
+ isDragging = true;
513
+ offsetX = e.clientX - node.getBoundingClientRect().left;
514
+ offsetY = e.clientY - node.getBoundingClientRect().top;
515
+ node.style.zIndex = 100;
516
+ node.style.cursor = 'grabbing';
517
+ });
518
+
519
+ document.addEventListener('mousemove', (e) => {
520
+ if (!isDragging) return;
521
+
522
+ const x = e.clientX - offsetX - mindMap.getBoundingClientRect().left;
523
+ const y = e.clientY - offsetY - mindMap.getBoundingClientRect().top;
524
+
525
+ node.style.left = `${x}px`;
526
+ node.style.top = `${y}px`;
527
+
528
+ // Update all connectors connected to this node
529
+ updateAllConnectors();
530
+ });
531
+
532
+ document.addEventListener('mouseup', () => {
533
+ isDragging = false;
534
+ node.style.zIndex = '';
535
+ node.style.cursor = 'move';
536
+ });
537
+ });
538
+ }
539
+
540
+ function updateAllConnectors() {
541
+ // This is a simplified version - in a real app you'd track which nodes are connected
542
+ connectors.forEach(connector => connector.remove());
543
+ connectors = [];
544
+
545
+ // Recreate connectors between main node and questions
546
+ if (nodes.length > 1) {
547
+ const mainNode = nodes[0];
548
+
549
+ for (let i = 1; i < nodes.length; i++) {
550
+ if (nodes[i].classList.contains('node-question')) {
551
+ createConnector(mainNode, nodes[i]);
552
+
553
+ // Connect question to its answer
554
+ if (i + 1 < nodes.length && nodes[i+1].classList.contains('node-answer')) {
555
+ createConnector(nodes[i], nodes[i+1]);
556
+ i++; // Skip the answer node in next iteration
557
+ }
558
+ }
559
+ }
560
+ }
561
+ }
562
+
563
+ function addQuestionNode() {
564
+ if (!currentTheme) {
565
+ alert('Veuillez sélectionner un thème d\'abord');
566
+ return;
567
+ }
568
+
569
+ const question = prompt('Entrez votre question:');
570
+ if (!question) return;
571
+
572
+ // Find main node
573
+ const mainNode = nodes[0];
574
+ if (!mainNode) return;
575
+
576
+ // Position new question node around main node
577
+ const angle = Math.random() * 2 * Math.PI;
578
+ const radius = 150;
579
+ const x = mainNode.offsetLeft + mainNode.offsetWidth / 2 + Math.cos(angle) * radius - 100;
580
+ const y = mainNode.offsetTop + mainNode.offsetHeight / 2 + Math.sin(angle) * radius - 50;
581
+
582
+ const questionNode = createNode(question, 'node-question', x, y);
583
+ nodes.push(questionNode);
584
+ createConnector(mainNode, questionNode);
585
+
586
+ makeNodesDraggable();
587
+ }
588
+
589
+ function addAnswerNode() {
590
+ const questionNodes = nodes.filter(node => node.classList.contains('node-question'));
591
+ if (questionNodes.length === 0) {
592
+ alert('Ajoutez d\'abord une question');
593
+ return;
594
+ }
595
+
596
+ // Find the last question node
597
+ const lastQuestionNode = questionNodes[questionNodes.length - 1];
598
+
599
+ const answer = prompt('Entrez la réponse:');
600
+ if (!answer) return;
601
+
602
+ // Position answer node near the question
603
+ const x = lastQuestionNode.offsetLeft + 120;
604
+ const y = lastQuestionNode.offsetTop + 120;
605
+
606
+ const answerNode = createNode(answer, 'node-answer', x, y);
607
+ nodes.push(answerNode);
608
+ createConnector(lastQuestionNode, answerNode);
609
+
610
+ makeNodesDraggable();
611
+ }
612
+
613
+ function addBlankNode() {
614
+ const answerNodes = nodes.filter(node => node.classList.contains('node-answer'));
615
+ if (answerNodes.length === 0) {
616
+ alert('Ajoutez d\'abord une réponse');
617
+ return;
618
+ }
619
+
620
+ // Add blank to the last answer node
621
+ addBlankToNode(answerNodes[answerNodes.length - 1]);
622
+ }
623
+
624
+ function addBlankToNode(node) {
625
+ const text = node.textContent;
626
+ const words = text.split(' ');
627
+
628
+ // Choose a random word (not too short)
629
+ let wordIndex;
630
+ do {
631
+ wordIndex = Math.floor(Math.random() * words.length);
632
+ } while (words[wordIndex].length < 3);
633
+
634
+ const wordToBlank = words[wordIndex];
635
+
636
+ // Replace the word with an input
637
+ words[wordIndex] = `<input type="text" class="blank-input" data-answer="${wordToBlank.toLowerCase()}" placeholder="...">`;
638
+
639
+ // Update node content
640
+ node.innerHTML = words.join(' ');
641
+
642
+ // Store blank info
643
+ blanks.push({
644
+ node: node,
645
+ answer: wordToBlank.toLowerCase(),
646
+ input: node.querySelector('.blank-input')
647
+ });
648
+
649
+ // Update blanks container
650
+ updateBlanksDisplay();
651
+ }
652
+
653
+ function updateBlanksDisplay() {
654
+ if (blanks.length === 0) {
655
+ blanksContainer.innerHTML = `
656
+ <div class="bg-gray-100 p-4 rounded-lg text-center w-full">
657
+ <p class="text-gray-500">Les trous que vous complétez apparaîtront ici pour vérification.</p>
658
+ </div>
659
+ `;
660
+ checkAnswersBtn.classList.add('hidden');
661
+ return;
662
+ }
663
+
664
+ blanksContainer.innerHTML = '';
665
+ checkAnswersBtn.classList.remove('hidden');
666
+
667
+ blanks.forEach((blank, index) => {
668
+ const blankElement = document.createElement('div');
669
+ blankElement.className = 'bg-gray-100 p-4 rounded-lg flex items-center';
670
+ blankElement.innerHTML = `
671
+ <span class="text-gray-700 mr-2">${index + 1}.</span>
672
+ <input type="text" class="flex-1 border border-gray-300 rounded px-3 py-1"
673
+ data-answer="${blank.answer}" placeholder="Votre réponse...">
674
+ <button class="ml-2 bg-blue-100 text-blue-600 px-3 py-1 rounded check-blank-btn">
675
+ <i class="fas fa-check"></i>
676
+ </button>
677
+ `;
678
+
679
+ blanksContainer.appendChild(blankElement);
680
+
681
+ // Add event listener to check button
682
+ blankElement.querySelector('.check-blank-btn').addEventListener('click', (e) => {
683
+ checkSingleBlank(e.target.closest('.bg-gray-100'));
684
+ });
685
+ });
686
+ }
687
+
688
+ function checkSingleBlank(blankElement) {
689
+ const input = blankElement.querySelector('input');
690
+ const userAnswer = input.value.trim().toLowerCase();
691
+ const correctAnswer = input.dataset.answer;
692
+
693
+ if (userAnswer === correctAnswer) {
694
+ blankElement.classList.remove('bg-gray-100');
695
+ blankElement.classList.add('bg-green-100');
696
+ input.classList.remove('border-gray-300');
697
+ input.classList.add('border-green-500');
698
+ } else {
699
+ blankElement.classList.remove('bg-gray-100');
700
+ blankElement.classList.add('bg-red-100');
701
+ input.classList.remove('border-gray-300');
702
+ input.classList.add('border-red-500');
703
+
704
+ // Show correct answer after a delay
705
+ setTimeout(() => {
706
+ input.value = correctAnswer;
707
+ }, 1000);
708
+ }
709
+ }
710
+
711
+ function checkAnswers() {
712
+ const blankInputs = blanksContainer.querySelectorAll('input');
713
+ let allCorrect = true;
714
+
715
+ blankInputs.forEach(input => {
716
+ const blankElement = input.closest('.bg-gray-100');
717
+ checkSingleBlank(blankElement);
718
+
719
+ if (input.value.trim().toLowerCase() !== input.dataset.answer) {
720
+ allCorrect = false;
721
+ }
722
+ });
723
+
724
+ if (allCorrect) {
725
+ setTimeout(() => {
726
+ alert('Félicitations ! Toutes vos réponses sont correctes.');
727
+ }, 500);
728
+ }
729
+ }
730
+ </script>
731
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Adam77/aide-aux-devoirs" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
732
+ </html>