SaidAmchghal commited on
Commit
cefaa66
·
verified ·
1 Parent(s): e941184

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +6 -4
  2. index.html +735 -19
  3. prompts.txt +2 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Transport
3
- emoji: 📈
4
  colorFrom: pink
5
- colorTo: indigo
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: transport
3
+ emoji: 🐳
4
  colorFrom: pink
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,735 @@
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>Optimisation de Trajet Transporteur</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
+ .map-container {
11
+ height: 400px;
12
+ background-color: #e5e7eb;
13
+ position: relative;
14
+ overflow: hidden;
15
+ }
16
+ .city-node {
17
+ position: absolute;
18
+ width: 24px;
19
+ height: 24px;
20
+ background-color: #3b82f6;
21
+ border-radius: 50%;
22
+ display: flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ color: white;
26
+ font-weight: bold;
27
+ cursor: pointer;
28
+ transform: translate(-50%, -50%);
29
+ box-shadow: 0 2px 4px rgba(0,0,0,0.2);
30
+ transition: all 0.2s;
31
+ z-index: 2;
32
+ }
33
+ .city-node:hover {
34
+ transform: translate(-50%, -50%) scale(1.2);
35
+ background-color: #2563eb;
36
+ }
37
+ .route-line {
38
+ position: absolute;
39
+ background-color: #ef4444;
40
+ height: 3px;
41
+ transform-origin: left center;
42
+ z-index: 1;
43
+ }
44
+ .optimal-route {
45
+ animation: pulse 2s infinite;
46
+ }
47
+ @keyframes pulse {
48
+ 0% { opacity: 0.7; }
49
+ 50% { opacity: 1; }
50
+ 100% { opacity: 0.7; }
51
+ }
52
+ .distance-matrix td {
53
+ min-width: 60px;
54
+ }
55
+ .loading-spinner {
56
+ display: inline-block;
57
+ width: 20px;
58
+ height: 20px;
59
+ border: 3px solid rgba(255,255,255,.3);
60
+ border-radius: 50%;
61
+ border-top-color: #fff;
62
+ animation: spin 1s ease-in-out infinite;
63
+ }
64
+ @keyframes spin {
65
+ to { transform: rotate(360deg); }
66
+ }
67
+ .progress-bar {
68
+ height: 4px;
69
+ background-color: #e5e7eb;
70
+ border-radius: 2px;
71
+ overflow: hidden;
72
+ margin-top: 8px;
73
+ }
74
+ .progress-bar-fill {
75
+ height: 100%;
76
+ background-color: #3b82f6;
77
+ transition: width 0.3s ease;
78
+ }
79
+ </style>
80
+ </head>
81
+ <body class="bg-gray-50 min-h-screen">
82
+ <div class="container mx-auto px-4 py-8">
83
+ <header class="mb-8 text-center">
84
+ <h1 class="text-3xl font-bold text-blue-600 mb-2">Optimisation de Trajet Transporteur</h1>
85
+ <p class="text-gray-600">Calcul du trajet le plus court pour visiter toutes les villes et retourner au point de départ</p>
86
+ </header>
87
+
88
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
89
+ <!-- Formulaire de saisie -->
90
+ <div class="bg-white rounded-lg shadow-md p-6">
91
+ <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2">Configuration du trajet</h2>
92
+
93
+ <div class="mb-6">
94
+ <label class="block text-gray-700 mb-2">Villes à visiter</label>
95
+ <div class="flex mb-2">
96
+ <input type="text" id="cityName" placeholder="Nom de la ville" class="flex-1 px-3 py-2 border rounded-l focus:outline-none focus:ring-2 focus:ring-blue-500">
97
+ <button id="addCityBtn" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-r">
98
+ <i class="fas fa-plus mr-1"></i> Ajouter
99
+ </button>
100
+ </div>
101
+ <ul id="citiesList" class="border rounded divide-y max-h-40 overflow-y-auto">
102
+ <!-- Villes ajoutées apparaîtront ici -->
103
+ </ul>
104
+ </div>
105
+
106
+ <div class="mb-6">
107
+ <label class="block text-gray-700 mb-2">Matrice des distances (km)</label>
108
+ <div class="overflow-x-auto">
109
+ <table id="distanceMatrix" class="w-full border-collapse distance-matrix">
110
+ <thead>
111
+ <tr class="bg-gray-100">
112
+ <th class="border p-2">Ville</th>
113
+ <!-- Colonnes seront ajoutées dynamiquement -->
114
+ </tr>
115
+ </thead>
116
+ <tbody>
117
+ <!-- Lignes seront ajoutées dynamiquement -->
118
+ </tbody>
119
+ </table>
120
+ </div>
121
+ </div>
122
+
123
+ <div class="flex justify-end space-x-3">
124
+ <button id="resetBtn" class="px-4 py-2 border border-gray-300 rounded text-gray-700 hover:bg-gray-100">
125
+ <i class="fas fa-redo mr-1"></i> Réinitialiser
126
+ </button>
127
+ <button id="calculateBtn" class="px-4 py-2 bg-green-500 hover:bg-green-600 text-white rounded flex items-center">
128
+ <i class="fas fa-calculator mr-1"></i> Calculer le trajet optimal
129
+ </button>
130
+ </div>
131
+ </div>
132
+
133
+ <!-- Résultats et visualisation -->
134
+ <div class="bg-white rounded-lg shadow-md p-6">
135
+ <h2 class="text-xl font-semibold mb-4 text-gray-800 border-b pb-2">Résultats</h2>
136
+
137
+ <div id="resultsContainer" class="hidden">
138
+ <div class="mb-4 p-4 bg-blue-50 rounded border border-blue-200">
139
+ <h3 class="font-medium text-blue-800 mb-2">Trajet optimal</h3>
140
+ <div id="optimalRoute" class="text-lg font-semibold text-blue-600"></div>
141
+ <div id="totalDistance" class="mt-2 text-gray-700"></div>
142
+ <div class="progress-bar hidden" id="progressBarContainer">
143
+ <div class="progress-bar-fill" id="progressBar"></div>
144
+ </div>
145
+ </div>
146
+
147
+ <div class="map-container mb-4 rounded border border-gray-200 relative">
148
+ <div id="map"></div>
149
+ </div>
150
+
151
+ <div class="bg-gray-50 p-4 rounded border border-gray-200">
152
+ <h3 class="font-medium text-gray-800 mb-2">Détails de l'algorithme</h3>
153
+ <div id="algorithmDetails" class="text-sm text-gray-600">
154
+ <!-- Détails du calcul apparaîtront ici -->
155
+ </div>
156
+ </div>
157
+ </div>
158
+
159
+ <div id="emptyState" class="text-center py-12 text-gray-500">
160
+ <i class="fas fa-route text-4xl mb-4 text-gray-300"></i>
161
+ <p>Ajoutez des villes et leurs distances, puis cliquez sur "Calculer" pour trouver le trajet optimal.</p>
162
+ </div>
163
+
164
+ <div id="loadingState" class="hidden text-center py-12">
165
+ <div class="inline-block mb-4">
166
+ <div class="loading-spinner"></div>
167
+ </div>
168
+ <p class="text-gray-600">Calcul du trajet optimal en cours...</p>
169
+ <div class="progress-bar mt-4 w-1/2 mx-auto">
170
+ <div class="progress-bar-fill" id="loadingProgressBar"></div>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+
177
+ <script>
178
+ document.addEventListener('DOMContentLoaded', function() {
179
+ const cities = [];
180
+ const distanceMatrix = {};
181
+ let cityCounter = 0;
182
+ let isCalculating = false;
183
+
184
+ // Éléments DOM
185
+ const cityNameInput = document.getElementById('cityName');
186
+ const addCityBtn = document.getElementById('addCityBtn');
187
+ const citiesList = document.getElementById('citiesList');
188
+ const distanceMatrixTable = document.getElementById('distanceMatrix');
189
+ const calculateBtn = document.getElementById('calculateBtn');
190
+ const resetBtn = document.getElementById('resetBtn');
191
+ const resultsContainer = document.getElementById('resultsContainer');
192
+ const emptyState = document.getElementById('emptyState');
193
+ const loadingState = document.getElementById('loadingState');
194
+ const optimalRouteDisplay = document.getElementById('optimalRoute');
195
+ const totalDistanceDisplay = document.getElementById('totalDistance');
196
+ const algorithmDetails = document.getElementById('algorithmDetails');
197
+ const mapContainer = document.getElementById('map');
198
+ const progressBarContainer = document.getElementById('progressBarContainer');
199
+ const progressBar = document.getElementById('progressBar');
200
+ const loadingProgressBar = document.getElementById('loadingProgressBar');
201
+
202
+ // Ajouter une ville
203
+ addCityBtn.addEventListener('click', function() {
204
+ const cityName = cityNameInput.value.trim();
205
+ if (cityName && !cities.includes(cityName)) {
206
+ cities.push(cityName);
207
+ distanceMatrix[cityName] = {};
208
+
209
+ // Initialiser les distances avec les villes existantes
210
+ cities.forEach(city => {
211
+ if (city !== cityName) {
212
+ distanceMatrix[cityName][city] = undefined;
213
+ distanceMatrix[city][cityName] = undefined;
214
+ }
215
+ });
216
+
217
+ // Mettre à jour la liste des villes
218
+ updateCitiesList();
219
+
220
+ // Mettre à jour la matrice des distances
221
+ updateDistanceMatrix();
222
+
223
+ // Effacer le champ de saisie
224
+ cityNameInput.value = '';
225
+
226
+ // Masquer l'état vide si nécessaire
227
+ if (cities.length >= 2) {
228
+ emptyState.classList.add('hidden');
229
+ }
230
+ }
231
+ });
232
+
233
+ // Ajouter une ville avec la touche Entrée
234
+ cityNameInput.addEventListener('keypress', function(e) {
235
+ if (e.key === 'Enter') {
236
+ addCityBtn.click();
237
+ }
238
+ });
239
+
240
+ // Mettre à jour la liste des villes
241
+ function updateCitiesList() {
242
+ citiesList.innerHTML = '';
243
+ cities.forEach(city => {
244
+ const li = document.createElement('li');
245
+ li.className = 'px-3 py-2 flex justify-between items-center hover:bg-gray-50';
246
+ li.innerHTML = `
247
+ <span>${city}</span>
248
+ <button class="text-red-500 hover:text-red-700 delete-city" data-city="${city}">
249
+ <i class="fas fa-times"></i>
250
+ </button>
251
+ `;
252
+ citiesList.appendChild(li);
253
+ });
254
+
255
+ // Ajouter des écouteurs d'événements pour les boutons de suppression
256
+ document.querySelectorAll('.delete-city').forEach(btn => {
257
+ btn.addEventListener('click', function() {
258
+ const cityToRemove = this.getAttribute('data-city');
259
+ removeCity(cityToRemove);
260
+ });
261
+ });
262
+ }
263
+
264
+ // Supprimer une ville
265
+ function removeCity(city) {
266
+ const index = cities.indexOf(city);
267
+ if (index !== -1) {
268
+ cities.splice(index, 1);
269
+ delete distanceMatrix[city];
270
+
271
+ // Supprimer les distances associées dans la matrice
272
+ for (const otherCity in distanceMatrix) {
273
+ if (distanceMatrix[otherCity][city]) {
274
+ delete distanceMatrix[otherCity][city];
275
+ }
276
+ }
277
+
278
+ updateCitiesList();
279
+ updateDistanceMatrix();
280
+
281
+ // Afficher l'état vide si nécessaire
282
+ if (cities.length < 2) {
283
+ resultsContainer.classList.add('hidden');
284
+ emptyState.classList.remove('hidden');
285
+ }
286
+ }
287
+ }
288
+
289
+ // Mettre à jour la matrice des distances
290
+ function updateDistanceMatrix() {
291
+ // Vider le tableau
292
+ distanceMatrixTable.innerHTML = '';
293
+
294
+ if (cities.length === 0) {
295
+ return;
296
+ }
297
+
298
+ // Créer l'en-tête
299
+ const thead = distanceMatrixTable.createTHead();
300
+ const headerRow = thead.insertRow();
301
+ headerRow.innerHTML = '<th class="border p-2">Ville</th>';
302
+
303
+ cities.forEach(city => {
304
+ const th = document.createElement('th');
305
+ th.className = 'border p-2';
306
+ th.textContent = city;
307
+ headerRow.appendChild(th);
308
+ });
309
+
310
+ // Créer le corps du tableau
311
+ const tbody = distanceMatrixTable.createTBody();
312
+
313
+ cities.forEach(city1 => {
314
+ const row = tbody.insertRow();
315
+ const cell = row.insertCell();
316
+ cell.className = 'border p-2 bg-gray-100 font-medium';
317
+ cell.textContent = city1;
318
+
319
+ cities.forEach(city2 => {
320
+ const cell = row.insertCell();
321
+ cell.className = 'border p-2';
322
+
323
+ if (city1 === city2) {
324
+ cell.innerHTML = '<span class="text-gray-400">-</span>';
325
+ } else {
326
+ const input = document.createElement('input');
327
+ input.type = 'number';
328
+ input.min = '0';
329
+ input.step = '0.1';
330
+ input.className = 'w-full px-2 py-1 border rounded focus:outline-none focus:ring-1 focus:ring-blue-500';
331
+ input.value = distanceMatrix[city1][city2] || '';
332
+ input.placeholder = 'km';
333
+
334
+ input.addEventListener('change', function() {
335
+ const value = parseFloat(this.value);
336
+ if (!isNaN(value) && value >= 0) {
337
+ distanceMatrix[city1][city2] = value;
338
+ distanceMatrix[city2][city1] = value; // Symétrique
339
+ } else {
340
+ delete distanceMatrix[city1][city2];
341
+ delete distanceMatrix[city2][city1];
342
+ this.value = '';
343
+ }
344
+ });
345
+
346
+ cell.appendChild(input);
347
+ }
348
+ });
349
+ });
350
+ }
351
+
352
+ // Réinitialiser l'application
353
+ resetBtn.addEventListener('click', function() {
354
+ if (isCalculating) return;
355
+
356
+ cities.length = 0;
357
+ for (const city in distanceMatrix) {
358
+ delete distanceMatrix[city];
359
+ }
360
+
361
+ updateCitiesList();
362
+ updateDistanceMatrix();
363
+ resultsContainer.classList.add('hidden');
364
+ loadingState.classList.add('hidden');
365
+ emptyState.classList.remove('hidden');
366
+ });
367
+
368
+ // Calculer le trajet optimal
369
+ calculateBtn.addEventListener('click', async function() {
370
+ if (isCalculating) return;
371
+
372
+ if (cities.length < 2) {
373
+ showAlert('Veuillez ajouter au moins 2 villes pour calculer un trajet.', 'error');
374
+ return;
375
+ }
376
+
377
+ // Vérifier que toutes les distances sont renseignées
378
+ let allDistancesSet = true;
379
+ const missingDistances = [];
380
+
381
+ for (let i = 0; i < cities.length; i++) {
382
+ for (let j = i + 1; j < cities.length; j++) {
383
+ const city1 = cities[i];
384
+ const city2 = cities[j];
385
+ if (typeof distanceMatrix[city1][city2] === 'undefined' ||
386
+ isNaN(distanceMatrix[city1][city2])) {
387
+ allDistancesSet = false;
388
+ missingDistances.push(`${city1} ↔ ${city2}`);
389
+ }
390
+ }
391
+ }
392
+
393
+ if (!allDistancesSet) {
394
+ showAlert(`Veuillez renseigner toutes les distances entre les villes.<br>Distances manquantes: ${missingDistances.join(', ')}`, 'error');
395
+ return;
396
+ }
397
+
398
+ // Démarrer le calcul
399
+ isCalculating = true;
400
+ resultsContainer.classList.add('hidden');
401
+ emptyState.classList.add('hidden');
402
+ loadingState.classList.remove('hidden');
403
+
404
+ try {
405
+ // Simuler un temps de calcul (pour la démo)
406
+ await simulateCalculationProgress();
407
+
408
+ // Calculer le trajet optimal
409
+ const { route, distance } = await solveTSP();
410
+
411
+ // Afficher les résultats
412
+ optimalRouteDisplay.textContent = route.join(' → ');
413
+ totalDistanceDisplay.textContent = `Distance totale: ${distance.toFixed(2)} km`;
414
+
415
+ // Détails de l'algorithme
416
+ algorithmDetails.innerHTML = `
417
+ <p class="mb-2"><strong>Méthode utilisée:</strong> Algorithme du plus proche voisin avec optimisation 2-opt</p>
418
+ <p class="mb-2"><strong>Nombre de villes:</strong> ${cities.length}</p>
419
+ <p class="mb-2"><strong>Complexité:</strong> O(n²) - Solution approchée pour le problème NP-difficile du voyageur de commerce</p>
420
+ <p><strong>Note:</strong> Cette solution n'est pas garantie d'être optimale mais fournit une bonne approximation en temps raisonnable.</p>
421
+ `;
422
+
423
+ // Afficher la visualisation
424
+ visualizeRoute(route);
425
+
426
+ // Afficher le conteneur de résultats
427
+ resultsContainer.classList.remove('hidden');
428
+ } catch (error) {
429
+ console.error('Erreur lors du calcul:', error);
430
+ showAlert('Une erreur est survenue lors du calcul du trajet optimal.', 'error');
431
+ } finally {
432
+ loadingState.classList.add('hidden');
433
+ isCalculating = false;
434
+ }
435
+ });
436
+
437
+ // Simuler une barre de progression pendant le calcul
438
+ async function simulateCalculationProgress() {
439
+ return new Promise(resolve => {
440
+ let progress = 0;
441
+ const interval = setInterval(() => {
442
+ progress += Math.random() * 10;
443
+ if (progress > 95) {
444
+ progress = 95; // Ne pas aller à 100% avant la fin réelle
445
+ }
446
+ loadingProgressBar.style.width = `${progress}%`;
447
+ }, 200);
448
+
449
+ // Simuler un temps de calcul variable selon le nombre de villes
450
+ const delay = Math.min(2000, cities.length * 200);
451
+
452
+ setTimeout(() => {
453
+ clearInterval(interval);
454
+ loadingProgressBar.style.width = '100%';
455
+ setTimeout(resolve, 300);
456
+ }, delay);
457
+ });
458
+ }
459
+
460
+ // Afficher une alerte
461
+ function showAlert(message, type = 'info') {
462
+ const alertDiv = document.createElement('div');
463
+ const bgColor = type === 'error' ? 'bg-red-50 border-red-200 text-red-800' : 'bg-blue-50 border-blue-200 text-blue-800';
464
+
465
+ alertDiv.className = `fixed top-4 right-4 p-4 rounded border ${bgColor} shadow-lg max-w-md z-50`;
466
+ alertDiv.innerHTML = `
467
+ <div class="flex items-start">
468
+ <i class="fas ${type === 'error' ? 'fa-exclamation-triangle' : 'fa-info-circle'} mr-2 mt-1"></i>
469
+ <div>${message}</div>
470
+ <button class="ml-4 text-gray-500 hover:text-gray-700" onclick="this.parentElement.parentElement.remove()">
471
+ <i class="fas fa-times"></i>
472
+ </button>
473
+ </div>
474
+ `;
475
+
476
+ document.body.appendChild(alertDiv);
477
+
478
+ // Supprimer automatiquement après 5 secondes
479
+ setTimeout(() => {
480
+ alertDiv.remove();
481
+ }, 5000);
482
+ }
483
+
484
+ // Algorithme pour résoudre le TSP (approche par plus proche voisin avec optimisation 2-opt)
485
+ async function solveTSP() {
486
+ // Si peu de villes, utiliser la force brute pour une solution exacte
487
+ if (cities.length <= 8) {
488
+ return bruteForceTSP();
489
+ }
490
+
491
+ // Sinon, utiliser l'heuristique du plus proche voisin avec optimisation 2-opt
492
+ return nearestNeighborWith2Opt();
493
+ }
494
+
495
+ // Force brute pour un nombre restreint de villes
496
+ function bruteForceTSP() {
497
+ // Générer toutes les permutations possibles (sans le point de départ fixe)
498
+ const permutations = generatePermutations(cities.slice(1));
499
+
500
+ let minDistance = Infinity;
501
+ let bestRoute = [];
502
+ let evaluated = 0;
503
+ const total = permutations.length;
504
+
505
+ // Pour chaque permutation, calculer la distance totale
506
+ permutations.forEach(perm => {
507
+ // Ajouter la ville de départ au début et à la fin
508
+ const currentRoute = [cities[0], ...perm, cities[0]];
509
+ let currentDistance = 0;
510
+
511
+ // Calculer la distance totale pour cette route
512
+ for (let i = 0; i < currentRoute.length - 1; i++) {
513
+ const from = currentRoute[i];
514
+ const to = currentRoute[i + 1];
515
+ currentDistance += distanceMatrix[from][to];
516
+ }
517
+
518
+ // Mettre à jour la meilleure route si nécessaire
519
+ if (currentDistance < minDistance) {
520
+ minDistance = currentDistance;
521
+ bestRoute = currentRoute;
522
+ }
523
+
524
+ // Mettre à jour la barre de progression
525
+ evaluated++;
526
+ const progress = (evaluated / total) * 100;
527
+ progressBar.style.width = `${progress}%`;
528
+ });
529
+
530
+ return {
531
+ route: bestRoute,
532
+ distance: minDistance
533
+ };
534
+ }
535
+
536
+ // Heuristique du plus proche voisin avec optimisation 2-opt
537
+ function nearestNeighborWith2Opt() {
538
+ // Étape 1: Construction initiale avec l'algorithme du plus proche voisin
539
+ let route = nearestNeighbor();
540
+ let improved = true;
541
+
542
+ // Afficher la progression initiale
543
+ progressBarContainer.classList.remove('hidden');
544
+ progressBar.style.width = '50%';
545
+
546
+ // Étape 2: Optimisation avec 2-opt
547
+ while (improved) {
548
+ improved = false;
549
+ const oldDistance = calculateRouteDistance(route);
550
+
551
+ for (let i = 1; i < route.length - 2; i++) {
552
+ for (let j = i + 1; j < route.length - 1; j++) {
553
+ // Essayer d'inverser la sous-route entre i et j
554
+ const newRoute = twoOptSwap(route, i, j);
555
+ const newDistance = calculateRouteDistance(newRoute);
556
+
557
+ if (newDistance < oldDistance) {
558
+ route = newRoute;
559
+ improved = true;
560
+ break;
561
+ }
562
+ }
563
+ if (improved) break;
564
+ }
565
+
566
+ // Mettre à jour la barre de progression
567
+ progressBar.style.width = `${50 + Math.random() * 40}%`;
568
+ }
569
+
570
+ progressBar.style.width = '100%';
571
+
572
+ return {
573
+ route: route,
574
+ distance: calculateRouteDistance(route)
575
+ };
576
+ }
577
+
578
+ // Algorithme du plus proche voisin
579
+ function nearestNeighbor() {
580
+ const startCity = cities[0];
581
+ const unvisited = new Set(cities.slice(1));
582
+ const route = [startCity];
583
+ let currentCity = startCity;
584
+
585
+ while (unvisited.size > 0) {
586
+ let nearestCity = null;
587
+ let minDist = Infinity;
588
+
589
+ // Trouver la ville non visitée la plus proche
590
+ unvisited.forEach(city => {
591
+ const dist = distanceMatrix[currentCity][city];
592
+ if (dist < minDist) {
593
+ minDist = dist;
594
+ nearestCity = city;
595
+ }
596
+ });
597
+
598
+ // Ajouter à la route et passer à cette ville
599
+ route.push(nearestCity);
600
+ unvisited.delete(nearestCity);
601
+ currentCity = nearestCity;
602
+ }
603
+
604
+ // Retourner à la ville de départ
605
+ route.push(startCity);
606
+ return route;
607
+ }
608
+
609
+ // Échange 2-opt
610
+ function twoOptSwap(route, i, j) {
611
+ const newRoute = route.slice(0, i);
612
+ newRoute.push(...route.slice(i, j + 1).reverse());
613
+ newRoute.push(...route.slice(j + 1));
614
+ return newRoute;
615
+ }
616
+
617
+ // Calculer la distance totale d'une route
618
+ function calculateRouteDistance(route) {
619
+ let distance = 0;
620
+ for (let i = 0; i < route.length - 1; i++) {
621
+ distance += distanceMatrix[route[i]][route[i + 1]];
622
+ }
623
+ return distance;
624
+ }
625
+
626
+ // Générer toutes les permutations d'un tableau
627
+ function generatePermutations(arr) {
628
+ if (arr.length <= 1) return [arr];
629
+
630
+ const result = [];
631
+
632
+ for (let i = 0; i < arr.length; i++) {
633
+ const current = arr[i];
634
+ const remaining = [...arr.slice(0, i), ...arr.slice(i + 1)];
635
+ const remainingPerms = generatePermutations(remaining);
636
+
637
+ for (const perm of remainingPerms) {
638
+ result.push([current, ...perm]);
639
+ }
640
+ }
641
+
642
+ return result;
643
+ }
644
+
645
+ // Visualiser la route sur la carte
646
+ function visualizeRoute(route) {
647
+ // Effacer la carte précédente
648
+ mapContainer.innerHTML = '';
649
+
650
+ // Positionner aléatoirement les villes sur la carte
651
+ const cityPositions = {};
652
+ const mapWidth = mapContainer.clientWidth;
653
+ const mapHeight = mapContainer.clientHeight;
654
+ const margin = 60;
655
+
656
+ // Positionner les villes en cercle pour une meilleure visualisation
657
+ const centerX = mapWidth / 2;
658
+ const centerY = mapHeight / 2;
659
+ const radius = Math.min(mapWidth, mapHeight) / 2 - margin;
660
+
661
+ cities.forEach((city, index) => {
662
+ const angle = (index / cities.length) * 2 * Math.PI;
663
+ const x = centerX + radius * Math.cos(angle);
664
+ const y = centerY + radius * Math.sin(angle);
665
+ cityPositions[city] = { x, y };
666
+
667
+ // Créer un point pour la ville
668
+ const cityNode = document.createElement('div');
669
+ cityNode.className = 'city-node';
670
+ cityNode.style.left = `${x}px`;
671
+ cityNode.style.top = `${y}px`;
672
+ cityNode.textContent = index + 1;
673
+ cityNode.title = city;
674
+ mapContainer.appendChild(cityNode);
675
+
676
+ // Ajouter le nom de la ville
677
+ const cityLabel = document.createElement('div');
678
+ cityLabel.className = 'absolute text-xs font-medium text-gray-800';
679
+ cityLabel.style.left = `${x + 15}px`;
680
+ cityLabel.style.top = `${y - 10}px`;
681
+ cityLabel.textContent = city;
682
+ mapContainer.appendChild(cityLabel);
683
+ });
684
+
685
+ // Dessiner les lignes de la route optimale
686
+ for (let i = 0; i < route.length - 1; i++) {
687
+ const fromCity = route[i];
688
+ const toCity = route[i + 1];
689
+
690
+ const fromPos = cityPositions[fromCity];
691
+ const toPos = cityPositions[toCity];
692
+
693
+ // Calculer la distance entre les points
694
+ const dx = toPos.x - fromPos.x;
695
+ const dy = toPos.y - fromPos.y;
696
+ const distance = Math.sqrt(dx * dx + dy * dy);
697
+
698
+ // Calculer l'angle
699
+ const angle = Math.atan2(dy, dx) * 180 / Math.PI;
700
+
701
+ // Créer la ligne
702
+ const line = document.createElement('div');
703
+ line.className = 'route-line optimal-route';
704
+ line.style.left = `${fromPos.x}px`;
705
+ line.style.top = `${fromPos.y}px`;
706
+ line.style.width = `${distance}px`;
707
+ line.style.transform = `rotate(${angle}deg)`;
708
+
709
+ // Ajouter une flèche à la fin (sauf pour le dernier segment)
710
+ if (i < route.length - 2) {
711
+ line.style.background = 'linear-gradient(90deg, rgba(239,68,68,0.7) 90%, transparent)';
712
+ }
713
+
714
+ mapContainer.appendChild(line);
715
+ }
716
+
717
+ // Ajouter une légende
718
+ const legend = document.createElement('div');
719
+ legend.className = 'absolute bottom-2 left-2 bg-white bg-opacity-80 p-2 rounded text-sm shadow';
720
+ legend.innerHTML = `
721
+ <div class="flex items-center mb-1">
722
+ <span class="inline-block w-3 h-3 bg-blue-500 rounded-full mr-2"></span>
723
+ <span>Ville</span>
724
+ </div>
725
+ <div class="flex items-center">
726
+ <span class="inline-block w-4 h-1 bg-red-500 mr-2"></span>
727
+ <span>Trajet optimal</span>
728
+ </div>
729
+ `;
730
+ mapContainer.appendChild(legend);
731
+ }
732
+ });
733
+ </script>
734
+ <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=SaidAmchghal/transport" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
735
+ </html>
prompts.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ Une application qui calcul le trajet le plus court à empreinter par un transporteur pour visiter un nombre donné de ville et clôturer sa visite par le retour à la ville de départ en utilisant l'algorithme du simplexe.
2
+ Complétez l'application pour que toutes les fonctionnalités fonctionnent correctement