tyriaa commited on
Commit
8cfa19e
·
1 Parent(s): 1caf2c7

4rd commit

Browse files
static/css/style.css ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Style général */
2
+ body {
3
+ font-family: 'Open Sans', sans-serif;
4
+ margin: 0;
5
+ padding: 0;
6
+ background-color: #f5f5f5;
7
+ }
8
+
9
+ .container {
10
+ max-width: 1400px;
11
+ margin: 0 auto;
12
+ padding: 20px;
13
+ }
14
+
15
+ /* Header */
16
+ header {
17
+ text-align: center;
18
+ margin-bottom: 20px;
19
+ }
20
+
21
+ header h1 {
22
+ color: #333;
23
+ margin: 0;
24
+ font-size: 2em;
25
+ }
26
+
27
+ .generated-time {
28
+ color: #666;
29
+ margin: 5px 0;
30
+ font-size: 0.9em;
31
+ }
32
+
33
+ /* Layout principal */
34
+ .traffic-map-container {
35
+ display: grid;
36
+ grid-template-columns: 300px 1fr;
37
+ gap: 20px;
38
+ margin-bottom: 20px;
39
+ }
40
+
41
+ /* Section trafic */
42
+ .traffic-info {
43
+ background: white;
44
+ padding: 20px;
45
+ border-radius: 8px;
46
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
47
+ }
48
+
49
+ .traffic-info h2 {
50
+ margin-top: 0;
51
+ color: #333;
52
+ }
53
+
54
+ .incident-summary {
55
+ margin-top: 20px;
56
+ }
57
+
58
+ /* Carte */
59
+ .map-section {
60
+ height: 500px;
61
+ border-radius: 8px;
62
+ overflow: hidden;
63
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
64
+ }
65
+
66
+ #leaflet-map {
67
+ height: 100%;
68
+ width: 100%;
69
+ }
70
+
71
+ /* Liste des incidents */
72
+ .incidents-section {
73
+ background: white;
74
+ padding: 20px;
75
+ border-radius: 8px;
76
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
77
+ }
78
+
79
+ .incidents-section h2 {
80
+ margin-top: 0;
81
+ color: #333;
82
+ }
83
+
84
+ .incident-list {
85
+ display: grid;
86
+ gap: 15px;
87
+ }
88
+
89
+ .incident-item {
90
+ display: flex;
91
+ align-items: flex-start;
92
+ padding: 15px;
93
+ background: #f8f9fa;
94
+ border-radius: 6px;
95
+ cursor: pointer;
96
+ transition: background-color 0.2s;
97
+ }
98
+
99
+ .incident-item:hover {
100
+ background: #e9ecef;
101
+ }
102
+
103
+ .incident-icon {
104
+ margin-right: 15px;
105
+ flex-shrink: 0;
106
+ }
107
+
108
+ .incident-details {
109
+ flex-grow: 1;
110
+ }
111
+
112
+ .incident-details h4 {
113
+ margin: 0 0 8px 0;
114
+ color: #333;
115
+ }
116
+
117
+ .incident-details p {
118
+ margin: 4px 0;
119
+ color: #666;
120
+ font-size: 0.9em;
121
+ }
122
+
123
+ .delay {
124
+ color: #dc3545;
125
+ font-weight: 600;
126
+ }
127
+
128
+ /* Popup de la carte */
129
+ .incident-popup {
130
+ padding: 5px;
131
+ }
132
+
133
+ .incident-popup h3 {
134
+ margin: 0 0 8px 0;
135
+ color: #333;
136
+ font-size: 1em;
137
+ }
138
+
139
+ .incident-popup p {
140
+ margin: 4px 0;
141
+ color: #666;
142
+ font-size: 0.9em;
143
+ }
144
+
145
+ /* RTM Traffic styles */
146
+ .rtm-traffic {
147
+ margin-bottom: 20px;
148
+ }
149
+
150
+ .rtm-period {
151
+ margin-bottom: 20px;
152
+ }
153
+
154
+ .rtm-section {
155
+ margin-bottom: 15px;
156
+ }
157
+
158
+ .transport-lines {
159
+ display: flex;
160
+ flex-wrap: wrap;
161
+ gap: 10px;
162
+ margin-top: 5px;
163
+ }
164
+
165
+ .line-badge {
166
+ display: inline-flex;
167
+ align-items: center;
168
+ padding: 5px 10px;
169
+ border-radius: 15px;
170
+ font-weight: 600;
171
+ cursor: pointer;
172
+ transition: background-color 0.2s;
173
+ }
174
+
175
+ .line-badge.metro {
176
+ background-color: #007bff;
177
+ color: white;
178
+ }
179
+
180
+ .line-badge.tram {
181
+ background-color: #28a745;
182
+ color: white;
183
+ }
184
+
185
+ .line-badge.bus {
186
+ background-color: #ffc107;
187
+ color: black;
188
+ }
189
+
190
+ .line-badge.other {
191
+ background-color: #6c757d;
192
+ color: white;
193
+ }
194
+
195
+ .line-badge.upcoming {
196
+ opacity: 0.7;
197
+ }
198
+
199
+ .perturbation-details {
200
+ display: none;
201
+ margin: 10px 0;
202
+ padding: 10px;
203
+ background: #f8f9fa;
204
+ border-radius: 5px;
205
+ }
206
+
207
+ .perturbation-details.active {
208
+ display: block;
209
+ }
210
+
211
+ .empty-message {
212
+ color: #6c757d;
213
+ font-style: italic;
214
+ }
215
+
216
+ /* Responsive */
217
+ @media (max-width: 768px) {
218
+ .traffic-map-container {
219
+ grid-template-columns: 1fr;
220
+ }
221
+
222
+ .container {
223
+ padding: 10px;
224
+ }
225
+
226
+ .map-section {
227
+ height: 400px;
228
+ }
229
+ }
static/js/traffic.js ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Variables globales pour la carte et les marqueurs
2
+ let map;
3
+ let markers = [];
4
+
5
+ function initMap() {
6
+ if (map) {
7
+ map.remove();
8
+ }
9
+
10
+ map = L.map('leaflet-map').setView([43.2965, 5.3698], 12);
11
+
12
+ L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
13
+ attribution: 'OpenStreetMap, CartoDB',
14
+ maxZoom: 19
15
+ }).addTo(map);
16
+
17
+ updateTrafficIncidents();
18
+ }
19
+
20
+ function clearMarkers() {
21
+ markers.forEach(marker => marker.remove());
22
+ markers = [];
23
+ }
24
+
25
+ function updateTrafficIncidents() {
26
+ fetch('/incidents')
27
+ .then(response => response.json())
28
+ .then(data => {
29
+ clearMarkers();
30
+ if (data.incidents) {
31
+ data.incidents.forEach(incident => {
32
+ const coordinates = incident.geometry.coordinates;
33
+
34
+ // Créer un marqueur pour chaque incident
35
+ const marker = L.marker([coordinates[1], coordinates[0]])
36
+ .addTo(map);
37
+
38
+ markers.push(marker);
39
+
40
+ // Créer le contenu du popup
41
+ let popupContent = `
42
+ <div class="incident-popup">
43
+ <h3>Incident</h3>
44
+ <p>${incident.properties.events[0].description}</p>
45
+ `;
46
+
47
+ if (incident.properties.delay) {
48
+ popupContent += `<p>Délai: ${incident.properties.delay}</p>`;
49
+ }
50
+
51
+ if (incident.properties.startTime) {
52
+ const startTime = new Date(incident.properties.startTime);
53
+ popupContent += `<p>Début: ${startTime.toLocaleString()}</p>`;
54
+ }
55
+
56
+ popupContent += '</div>';
57
+
58
+ // Ajouter le popup au marqueur
59
+ const popup = L.popup()
60
+ .setLatLng([coordinates[1], coordinates[0]])
61
+ .setContent(popupContent);
62
+
63
+ marker.bindPopup(popup);
64
+ });
65
+ }
66
+ })
67
+ .catch(error => console.error('Erreur:', error));
68
+ }
69
+
70
+ // Mettre à jour les incidents toutes les 5 minutes
71
+ setInterval(updateTrafficIncidents, 5 * 60 * 1000);
72
+
73
+ // Initialiser la carte au chargement de la page
74
+ document.addEventListener('DOMContentLoaded', initMap);
templates/marseille_traffic.html CHANGED
@@ -8,475 +8,9 @@
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
  <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet">
10
  <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css">
 
11
  <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
12
- <style>
13
- body {
14
- margin: 0;
15
- padding: 0;
16
- font-family: 'Open Sans', sans-serif;
17
- display: flex;
18
- flex-direction: column;
19
- }
20
-
21
- .header {
22
- background-color: #004494;
23
- color: white;
24
- padding: 8px;
25
- text-align: center;
26
- }
27
-
28
- .header h1 {
29
- margin: 0;
30
- font-size: 18px;
31
- }
32
-
33
- .header .last-update {
34
- color: white;
35
- font-size: 12px;
36
- margin-top: 2px;
37
- }
38
-
39
- .main-section {
40
- display: flex;
41
- margin: 0 50px;
42
- background: white;
43
- height: 80vh;
44
- }
45
-
46
- .left-panel {
47
- width: 500px;
48
- overflow-y: auto;
49
- background: white;
50
- padding: 20px;
51
- border-right: 1px solid #e0e0e0;
52
- }
53
-
54
- .map-section {
55
- flex: 1;
56
- position: relative;
57
- background: white;
58
- }
59
-
60
- #leaflet-map {
61
- position: absolute;
62
- top: 0;
63
- left: 0;
64
- right: 0;
65
- bottom: 0;
66
- width: 100%;
67
- height: 100%;
68
- z-index: 1;
69
- }
70
-
71
- .ferries-section {
72
- margin: 20px 50px;
73
- padding: 20px;
74
- background: white;
75
- border-radius: 10px;
76
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
77
- }
78
-
79
- .ship-schedules {
80
- margin-top: 20px;
81
- padding: 15px;
82
- background: #f5f5f5;
83
- border-radius: 5px;
84
- }
85
-
86
- .ship-schedules h3 {
87
- margin: 0 0 15px 0;
88
- color: #333;
89
- }
90
-
91
- .ship-departures, .ship-arrivals {
92
- margin-top: 15px;
93
- }
94
-
95
- .ship-item {
96
- padding: 10px;
97
- margin: 5px 0;
98
- background: white;
99
- border-radius: 3px;
100
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
101
- }
102
-
103
- .ship-item h5 {
104
- margin: 0;
105
- color: #333;
106
- font-weight: 600;
107
- }
108
-
109
- .ship-item p {
110
- margin: 3px 0;
111
- font-size: 0.9em;
112
- color: #666;
113
- }
114
-
115
- .ship-item .time {
116
- color: #0066cc;
117
- font-weight: 500;
118
- }
119
-
120
- .ship-item .cut-off {
121
- color: #cc0000;
122
- font-size: 0.85em;
123
- }
124
-
125
- .last-update {
126
- font-size: 0.8em;
127
- color: #666;
128
- margin: 5px 0 15px 0;
129
- font-style: italic;
130
- }
131
-
132
- /* Styles pour le conteneur des navires */
133
- .ships-container {
134
- margin-top: 20px;
135
- width: 100%;
136
- background: rgba(255, 255, 255, 0.9);
137
- padding: 20px 0;
138
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
139
- }
140
-
141
- .ships-section {
142
- margin-bottom: 20px;
143
- }
144
-
145
- .ships-scroll-container {
146
- width: 100%;
147
- background: #fff;
148
- border: 1px solid #ddd;
149
- border-radius: 5px;
150
- padding: 10px;
151
- }
152
-
153
- .ships-scroll {
154
- padding: 10px 0;
155
- }
156
-
157
- .ship-item {
158
- display: block;
159
- margin: 10px 0;
160
- padding: 15px 20px;
161
- background: #f8f9fa;
162
- border-radius: 5px;
163
- font-size: 1.2em;
164
- line-height: 1.4;
165
- }
166
-
167
- .ships-section h3 {
168
- font-size: 1.5em;
169
- margin: 15px 0;
170
- color: #333;
171
- }
172
-
173
- .ship-time {
174
- color: #ff0000;
175
- font-weight: bold;
176
- font-size: 1.1em;
177
- }
178
-
179
- .last-update {
180
- margin-bottom: 20px;
181
- color: #666;
182
- font-size: 0.9em;
183
- }
184
-
185
- /* Ajout de styles pour les tables */
186
- .table-responsive {
187
- overflow-x: auto;
188
- }
189
-
190
- .table {
191
- width: 100%;
192
- border-collapse: collapse;
193
- }
194
-
195
- .table th, .table td {
196
- border: 1px solid #ddd;
197
- padding: 8px;
198
- text-align: left;
199
- }
200
-
201
- .table th {
202
- background-color: #f0f0f0;
203
- }
204
-
205
- .ships-container {
206
- margin: 20px;
207
- padding: 20px;
208
- background: white;
209
- border-radius: 10px;
210
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
211
- }
212
-
213
- .ships-section {
214
- margin-bottom: 20px;
215
- }
216
-
217
- .ships-section h3 {
218
- color: #333;
219
- margin: 10px 0;
220
- padding: 10px;
221
- background: #f8f9fa;
222
- border-radius: 5px;
223
- font-size: 1.2em;
224
- }
225
-
226
- .ships-scroll-container {
227
- width: 100%;
228
- background: #fff;
229
- border: 1px solid #ddd;
230
- border-radius: 5px;
231
- padding: 10px;
232
- }
233
-
234
- .ships-scroll {
235
- padding: 10px 0;
236
- }
237
-
238
- .ship-item {
239
- display: block;
240
- margin: 10px 0;
241
- padding: 10px 15px;
242
- background: #f8f9fa;
243
- border-radius: 5px;
244
- font-size: 0.9em;
245
- }
246
-
247
- .last-update {
248
- margin-bottom: 20px;
249
- color: #666;
250
- font-size: 0.9em;
251
- }
252
-
253
- .traffic-info {
254
- padding: 15px;
255
- background: white;
256
- border-radius: 5px;
257
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
258
- margin-right: 20px;
259
- max-height: 600px;
260
- overflow-y: auto;
261
- }
262
-
263
- .rtm-line {
264
- margin-bottom: 15px;
265
- padding: 10px;
266
- border-radius: 5px;
267
- background: #f8f9fa;
268
- }
269
-
270
- .rtm-line h3 {
271
- margin: 0 0 10px 0;
272
- color: #333;
273
- font-size: 1.2em;
274
- }
275
-
276
- .rtm-line .content {
277
- font-size: 0.95em;
278
- line-height: 1.4;
279
- color: #666;
280
- }
281
-
282
- .rtm-line.metro { border-left: 4px solid #0066cc; }
283
- .rtm-line.bus { border-left: 4px solid #ff9900; }
284
- .rtm-line.tram { border-left: 4px solid #33cc33; }
285
-
286
- /* Styles pour les perturbations RTM */
287
- .rtm-traffic {
288
- margin: 20px 0;
289
- padding: 15px;
290
- background: #fff;
291
- border-radius: 8px;
292
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
293
- }
294
-
295
- .rtm-section {
296
- margin-bottom: 20px;
297
- }
298
-
299
- .rtm-section h3 {
300
- color: #333;
301
- margin-bottom: 10px;
302
- padding-bottom: 5px;
303
- border-bottom: 2px solid #f0f0f0;
304
- }
305
-
306
- .transport-lines {
307
- display: flex;
308
- flex-wrap: wrap;
309
- gap: 10px;
310
- }
311
-
312
- .line-badge {
313
- padding: 8px 15px;
314
- border-radius: 20px;
315
- font-weight: 600;
316
- cursor: pointer;
317
- transition: all 0.3s ease;
318
- }
319
-
320
- .line-badge:hover {
321
- transform: translateY(-2px);
322
- box-shadow: 0 2px 5px rgba(0,0,0,0.2);
323
- }
324
-
325
- .line-badge.metro {
326
- background-color: #0055A4;
327
- color: white;
328
- }
329
-
330
- .line-badge.bus {
331
- background-color: #3498db;
332
- color: white;
333
- }
334
-
335
- .line-badge.tram {
336
- background-color: #27ae60;
337
- color: white;
338
- }
339
-
340
- .line-badge.other {
341
- background-color: #95a5a6;
342
- color: white;
343
- }
344
-
345
- .perturbation-details {
346
- display: none;
347
- margin-top: 10px;
348
- padding: 15px;
349
- background: #f8f9fa;
350
- border-radius: 5px;
351
- border-left: 4px solid #0055A4;
352
- }
353
-
354
- .perturbation-details.active {
355
- display: block;
356
- }
357
-
358
- .perturbation-details h4 {
359
- margin: 0 0 10px 0;
360
- color: #333;
361
- }
362
-
363
- .perturbation-details p {
364
- margin: 5px 0;
365
- color: #666;
366
- }
367
-
368
- .perturbation-details .validity {
369
- font-style: italic;
370
- color: #e74c3c;
371
- }
372
-
373
- .rtm-period {
374
- margin: 20px 0;
375
- padding: 20px;
376
- background: #f8f9fa;
377
- border-radius: 8px;
378
- }
379
-
380
- .rtm-period h3 {
381
- color: #2c3e50;
382
- margin-bottom: 20px;
383
- padding-bottom: 10px;
384
- border-bottom: 2px solid #e74c3c;
385
- }
386
-
387
- .upcoming-disruptions .line-badge {
388
- border: 2px dashed;
389
- opacity: 0.8;
390
- }
391
-
392
- .upcoming-disruptions .line-badge:hover {
393
- opacity: 1;
394
- }
395
-
396
- .rtm-section h4 {
397
- color: #34495e;
398
- margin: 15px 0 10px 0;
399
- }
400
-
401
- .empty-message {
402
- color: #7f8c8d;
403
- font-style: italic;
404
- padding: 10px;
405
- }
406
-
407
- .incident-popup {
408
- padding: 10px;
409
- max-width: 300px;
410
- }
411
-
412
- .incident-popup h4 {
413
- margin: 0 0 10px 0;
414
- color: #004494;
415
- font-size: 16px;
416
- }
417
-
418
- .incident-popup p {
419
- margin: 5px 0;
420
- font-size: 14px;
421
- }
422
-
423
- .incident-popup .warning {
424
- color: #ff0000;
425
- font-weight: bold;
426
- }
427
-
428
- .custom-div-icon {
429
- background: none;
430
- border: none;
431
- }
432
-
433
- .incident-marker {
434
- display: flex;
435
- align-items: center;
436
- justify-content: center;
437
- }
438
-
439
- .marker-icon {
440
- width: 24px;
441
- height: 24px;
442
- border-radius: 50%;
443
- border: 2px solid white;
444
- box-shadow: 0 0 4px rgba(0,0,0,0.4);
445
- }
446
-
447
- /* Styles pour les différents types d'incidents */
448
- .marker-icon.1 { background-color: #ff0000; } /* Accident */
449
- .marker-icon.2 { background-color: #808080; } /* Brouillard */
450
- .marker-icon.3 { background-color: #ff4500; } /* Conditions dangereuses */
451
- .marker-icon.4 { background-color: #4169e1; } /* Pluie */
452
- .marker-icon.5 { background-color: #87ceeb; } /* Verglas */
453
- .marker-icon.6 { background-color: #ffa500; } /* Embouteillage */
454
- .marker-icon.7 { background-color: #ff6347; } /* Voie fermée */
455
- .marker-icon.8 { background-color: #dc143c; } /* Route fermée */
456
- .marker-icon.9 { background-color: #ffd700; } /* Travaux routiers */
457
- .marker-icon.10 { background-color: #00bfff; } /* Vent */
458
- .marker-icon.11 { background-color: #4682b4; } /* Inondation */
459
- .marker-icon.14 { background-color: #daa520; } /* Véhicule en panne */
460
- .marker-icon.default { background-color: #666666; }
461
-
462
- .incident-popup {
463
- padding: 10px;
464
- max-width: 250px;
465
- }
466
-
467
- .incident-popup h3 {
468
- margin: 0 0 10px 0;
469
- font-size: 14px;
470
- font-weight: bold;
471
- color: #333;
472
- }
473
-
474
- .incident-popup p {
475
- margin: 5px 0;
476
- font-size: 12px;
477
- color: #666;
478
- }
479
- </style>
480
  </head>
481
  <body>
482
  <div class="header">
 
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
  <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet">
10
  <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css">
11
+ <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
12
  <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
13
+ <script src="{{ url_for('static', filename='js/traffic.js') }}"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  </head>
15
  <body>
16
  <div class="header">