OUAREDAEK commited on
Commit
cbfc47f
·
verified ·
1 Parent(s): 659bd00

Upload templates/index.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. templates/index.html +297 -339
templates/index.html CHANGED
@@ -468,13 +468,12 @@ button:disabled {
468
 
469
  .compact-competences-grid {
470
  display: grid;
471
- grid-template-columns: repeat(4, 1fr); /* 4 colonnes */
472
- grid-template-rows: repeat(3, auto); /* 3 lignes */
473
  gap: 10px;
474
  margin: 10px 0;
475
  }
476
 
477
- /* HAUTEUR RÉDUITE À 50% DES BOX DE COMPÉTENCES */
478
  .compact-competence-matrix-item {
479
  padding: 1px;
480
  background: linear-gradient(135deg, #f8f9fa, #e9ecef);
@@ -494,7 +493,6 @@ button:disabled {
494
  background: linear-gradient(135deg, #e3f2fd, #bbdefb);
495
  }
496
 
497
- /* POLICE AUGMENTÉE POUR LES LABELS DES COMPÉTENCES */
498
  .compact-matrix-competence-label {
499
  font-size: 12px;
500
  font-weight: 600;
@@ -2046,7 +2044,7 @@ Bienvenue sur notre outil d'évaluation qualitative des messages auto-réflexifs
2046
  <span>🕖</span> Indicateurs de la gestion du temps et régularité
2047
  </h5>
2048
  <div class="compact-persistence-indicators">
2049
- <div class="compact-indicator">
2050
  <span class="compact-indicator-dot" style="background:#FF6B6B;"></span>
2051
  <span>
2052
  Régularité du travail :
@@ -2054,28 +2052,28 @@ Bienvenue sur notre outil d'évaluation qualitative des messages auto-réflexifs
2054
  </span>
2055
  </div>
2056
 
2057
- <div style="margin-left: 18px; margin-top: 0; font-size: 12px; color: #888;">
2058
  La constance de l'activité de l'apprenant dans le temps.
2059
  </div>
2060
 
2061
- <div class="compact-indicator">
2062
  <span class="compact-indicator-dot" style="background:#FFD166;"></span>
2063
  <span>Gestion des échéances : <strong id="compact-deadlineScore">-</strong></span>
2064
  </div>
2065
 
2066
- <div style="margin-left: 18px; margin-top: 0; font-size: 12px; color: #888;">
2067
  La capacité de l'apprenant à respecter les délais.
2068
  </div>
2069
 
2070
- <div class="compact-indicator" style="margin-top: 10px;">
2071
  <span class="compact-indicator-dot" style="background:#4ECDC4;"></span>
2072
  <span>
2073
  <strong>Schéma d'effort :</strong>
2074
- <span id="compact-effortPattern">- </span>
2075
  </span>
2076
  </div>
2077
 
2078
- <div style="margin-left: 18px; margin-top: 0; font-size: 12px; color: #888;">
2079
  La dynamique temporelle de l'effort.
2080
  </div>
2081
  </div>
@@ -2345,7 +2343,7 @@ const trustWeights = {
2345
  // URL du script Google Apps Script pour la sauvegarde
2346
  const GOOGLE_SCRIPT_URL = 'https://script.google.com/macros/s/AKfycbyB_Q1RH9IctsE_jEbZUmyxv4WXlpGFFgtyEUsLmV72W3htK1YO3GSeoyjQIoWCKEod/exec';
2347
 
2348
- // SCÉNARIOS PAR DÉFAUT (14 profils)
2349
  const DEFAULT_SCENARIOS = [
2350
  { id: 1, title: "Étudiant engagé", manifest: { type: "Engagement élevé", manifeste: "Je suis très motivé et j'essaie de faire toutes les activités", description: "Étudiant avec un fort engagement et une régularité dans le travail" } },
2351
  { id: 2, title: "Étudiant actif mais inefficace", manifest: { type: "Activité désorganisée", manifeste: "Je travaille beaucoup mais je ne vois pas les résultats", description: "Beaucoup d'effort mais peu de résultats concrets" } },
@@ -2360,7 +2358,9 @@ const DEFAULT_SCENARIOS = [
2360
  { id: 11, title: "Étudiant en progression", manifest: { type: "Amélioration technique", manifeste: "Mes compétences techniques s'améliorent régulièrement", description: "Développement progressif des compétences techniques" } },
2361
  { id: 12, title: "Étudiant acceptant l'échec", manifest: { type: "Résilience", manifeste: "Je vois l'échec comme une opportunité d'apprendre", description: "Attitude positive face aux erreurs et échecs" } },
2362
  { id: 13, title: "Étudiant inactif", manifest: { type: "Inactivité", manifeste: "Je ne trouve pas la motivation pour commencer", description: "Très faible participation et engagement" } },
2363
- { id: 14, title: "Étudiant non engagé", manifest: { type: "Désengagement", manifeste: "Ce cours ne m'intéresse pas vraiment", description: "Manque d'intérêt et d'implication" } }
 
 
2364
  ];
2365
 
2366
  // MAPPING PERSÉVÉRANCE PAR PROFIL
@@ -2368,86 +2368,134 @@ const perseveranceProfiles = {
2368
  "Étudiant engagé": {
2369
  level: "Très élevée",
2370
  interpretation: "Efforts constants, persévère même face aux difficultés",
2371
- color: "#43A047"
 
 
 
2372
  },
2373
  "Étudiant actif mais inefficace": {
2374
  level: "Moyenne",
2375
  interpretation: "Efforts importants mais mal régulés, persévérance peu productive",
2376
- color: "#FB8C00"
 
 
 
2377
  },
2378
  "Étudiant orienté vers le succès": {
2379
  level: "Élevée",
2380
  interpretation: "Persévérance principalement guidée par l'atteinte des objectifs",
2381
- color: "#4CAF50"
 
 
 
2382
  },
2383
  "Étudiant motivé": {
2384
  level: "Élevée",
2385
  interpretation: "Engagement soutenu et continuité stable de l'effort",
2386
- color: "#4CAF50"
 
 
 
2387
  },
2388
  "Étudiant surmotivé": {
2389
  level: "Très élevée",
2390
  interpretation: "Effort intense, parfois excessif, avec risque de surcharge",
2391
- color: "#43A047"
 
 
 
2392
  },
2393
  "Étudiant stratégique": {
2394
  level: "Élevée",
2395
  interpretation: "Effort bien dosé, persévérance optimisée selon le rendement attendu",
2396
- color: "#4CAF50"
 
 
 
2397
  },
2398
  "Étudiant en amélioration": {
2399
  level: "Moyenne à élevée",
2400
  interpretation: "Efforts croissants, persévérance en cours de structuration",
2401
- color: "#FF9800"
 
 
 
2402
  },
2403
  "Étudiant en difficulté": {
2404
  level: "Faible",
2405
  interpretation: "Découragement fréquent et difficulté à maintenir l'effort",
2406
- color: "#E53935"
 
 
 
2407
  },
2408
  "Étudiant évitant l'échec": {
2409
  level: "Moyenne",
2410
  interpretation: "Persévérance motivée par la peur de l'échec plutôt que par l'apprentissage",
2411
- color: "#FB8C00"
 
 
 
2412
  },
2413
  "Étudiant à risque": {
2414
  level: "Très faible",
2415
  interpretation: "Abandon rapide et très faible tolérance à l'effort",
2416
- color: "#C62828"
 
 
 
2417
  },
2418
  "Étudiant en progression": {
2419
  level: "Élevée",
2420
  interpretation: "Efforts réguliers et de mieux en mieux maîtrisés",
2421
- color: "#4CAF50"
 
 
 
2422
  },
2423
  "Étudiant acceptant l'échec": {
2424
  level: "Élevée",
2425
  interpretation: "Bonne résilience, persévère malgré les erreurs et les échecs",
2426
- color: "#4CAF50"
 
 
 
2427
  },
2428
  "Étudiant inactif": {
2429
  level: "Très faible",
2430
  interpretation: "Manque d'engagement, difficulté à initier et maintenir l'effort",
2431
- color: "#C62828"
 
 
 
2432
  },
2433
  "Étudiant non engagé": {
2434
  level: "Faible",
2435
  interpretation: "Manque de motivation, faible persévérance dans l'effort",
2436
- color: "#E53935"
 
 
 
2437
  },
2438
  "Étudiant persévérant": {
2439
- level: "Moyenne à élevée",
2440
- interpretation: "Efforts maintenus malgré les doutes, persévérance réelle mais freinée par le manque de confiance",
2441
- color: "#FF9800"
2442
- },
2443
- "Étudiant actif": {
2444
- level: "Élevée",
2445
- interpretation: "Forte implication et nombreux efforts, mais difficulté à maintenir l'énergie jusqu'au bout",
2446
- color: "#4CAF50"
2447
- }
 
 
 
 
 
 
2448
  };
2449
 
2450
- // Messages de profils complets (14 profils)
2451
  const profileMessages = {
2452
  "Étudiant engagé": {
2453
  title: "Démarrage Rapide & Engagement Soutenu",
@@ -2576,23 +2624,23 @@ const profileMessages = {
2576
  ]
2577
  },
2578
  "Étudiant persévérant": {
2579
- title: "Efforts Réels malgré le Doute",
2580
- message: "Tu avances avec persévérance malgré des doutes sur toi-même. Tu démarres 55% des activités et en termines 58%. Tes résultats montrent que tes capacités sont bien là, même si tu hésites encore à te faire confiance.",
2581
- insights: [
2582
- { icon: "🌱", text: "Efforts constants malgré les doutes" },
2583
- { icon: "🧠", text: "Compétences bien présentes (66%)" },
2584
- { icon: "💪", text: "Persévérance visible" }
2585
- ]
2586
- },
2587
- "Étudiant actif": {
2588
- title: "Engagement Fort mais Énergie à Préserver",
2589
- message: "Tu démarres beaucoup d'activités (85%) et tu t'appuies largement sur les ressources (75%). Cet engagement montre ta motivation, mais il rend parfois difficile l'achèvement des tâches (45%). Mieux répartir tes efforts t'aidera à avancer plus sereinement.",
2590
- insights: [
2591
- { icon: "⚡", text: "Engagement élevé dès le départ (85%)" },
2592
- { icon: "📚", text: "Usage fréquent des ressources (75%)" },
2593
- { icon: "🧘", text: "Besoin de mieux doser l'effort" }
2594
- ]
2595
- }
2596
  };
2597
 
2598
  // ================= INIT =================
@@ -2699,7 +2747,7 @@ function loadScenarios() {
2699
  function tryLoad(pathIndex) {
2700
  if (pathIndex >= possiblePaths.length) {
2701
  console.error("❌ Impossible de charger les scénarios depuis aucun chemin");
2702
- console.log("Utilisation des scénarios par défaut (14 profils)");
2703
  scenarios = generateDefaultScenarios();
2704
 
2705
  if (scenarios.length === 0) {
@@ -2742,7 +2790,7 @@ function loadScenarios() {
2742
 
2743
  // Générer les scénarios par défaut
2744
  function generateDefaultScenarios() {
2745
- console.log("Génération des 14 scénarios par défaut");
2746
 
2747
  const defaultScenarios = [...DEFAULT_SCENARIOS];
2748
 
@@ -2835,6 +2883,12 @@ function generateProfileRadarData(profileTitle) {
2835
  case "Étudiant non engagé":
2836
  baseValues = [30, 35, 32, 75, 25, 40, 38];
2837
  break;
 
 
 
 
 
 
2838
  default:
2839
  baseValues = [70, 65, 62, 50, 65, 70, 68];
2840
  }
@@ -2864,7 +2918,7 @@ function generateReflAgentMessage(profileTitle) {
2864
  "Étudiant inactif": "Le premier pas est le plus difficile. Choisis une seule activité simple pour commencer, sans pression.",
2865
  "Étudiant non engagé": "Il est normal de manquer d'intérêt parfois. Cherche un aspect du cours qui pourrait te motiver davantage.",
2866
  "Étudiant persévérant": "Tes compétences sont solides. Fais confiance à ton potentiel et ose t'investir pleinement.",
2867
- "Étudiant actif": "Il est normal de manquer d'intérêt parfois. Cherche un aspect du cours qui pourrait te motiver davantage."
2868
  };
2869
 
2870
  return messages[profileTitle] || "Analyse de votre profil d'apprentissage en cours...";
@@ -2886,7 +2940,9 @@ function calculateRiskLevel(profileTitle) {
2886
  "Étudiant en progression": 40,
2887
  "Étudiant acceptant l'échec": 55,
2888
  "Étudiant inactif": 90,
2889
- "Étudiant non engagé": 75
 
 
2890
  };
2891
 
2892
  return riskLevels[profileTitle] || 50;
@@ -3256,6 +3312,16 @@ function drawCompactEnrichedHeatmapWithAxes(scenario) {
3256
  title: "Désengagement",
3257
  emoji: "😑",
3258
  pattern: "Activité sporadique et décroissante"
 
 
 
 
 
 
 
 
 
 
3259
  }
3260
  };
3261
 
@@ -3348,6 +3414,116 @@ function drawCompactEnrichedHeatmapWithAxes(scenario) {
3348
 
3349
  // Analyser et afficher les métriques de persévérance compactes
3350
  analyzeCompactPersistenceMetrics(activityData, scenario.id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3351
  }
3352
 
3353
  // Mettre à jour la persévérance spécifique au profil
@@ -3369,8 +3545,27 @@ function updatePerseveranceProfile(scenarioTitle) {
3369
  return;
3370
  }
3371
 
3372
- // Mettre à jour l'interface
 
 
 
3373
  const regularityText = document.getElementById("compact-regularityText");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3374
  if (regularityText) {
3375
  regularityText.innerHTML = `
3376
  <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 5px;">
@@ -3382,149 +3577,51 @@ function updatePerseveranceProfile(scenarioTitle) {
3382
  </div>
3383
  `;
3384
  }
3385
-
3386
- // Mettre à jour le score de régularité dans les indicateurs
3387
- const regularityScore = document.getElementById("compact-regularityScore");
3388
- if (regularityScore) {
3389
- // Convertir le niveau textuel en pourcentage approximatif
3390
- let scorePercent;
3391
- if (profile.level.includes("Très élevée")) scorePercent = "90%";
3392
- else if (profile.level.includes("Élevée")) scorePercent = "75%";
3393
- else if (profile.level.includes("Moyenne")) scorePercent = "55%";
3394
- else if (profile.level.includes("Faible")) scorePercent = "35%";
3395
- else if (profile.level.includes("Très faible")) scorePercent = "20%";
3396
- else scorePercent = "50%";
3397
-
3398
- regularityScore.textContent = scorePercent;
3399
- regularityScore.style.color = profile.color;
3400
- }
3401
  }
3402
 
3403
  // Générer des données de persévérance compactes
3404
  function generateCompactPersistenceData(scenarioId, totalDays) {
3405
  const data = new Array(totalDays).fill(0);
3406
 
3407
- switch(scenarioId) {
3408
- case 1: // Étudiant engagé - Effort concentré avant échéances
3409
- for (let i = 0; i < totalDays; i++) {
3410
- const weekday = i % 7;
3411
- if (weekday === 3 || weekday === 4) { // Jeudi et vendredi
3412
- data[i] = Math.floor(Math.random() * 2) + 3; // 3-4
3413
- } else if (weekday === 5 || weekday === 6) { // Weekend
3414
- data[i] = Math.floor(Math.random() * 2); // 0-1
3415
- } else {
3416
- data[i] = Math.floor(Math.random() * 2) + 1; // 1-2
3417
- }
3418
- }
3419
- break;
3420
-
3421
- case 2: // Étudiant actif mais inefficace - Démarrage lent, accélération tardive
3422
- for (let i = 0; i < totalDays; i++) {
3423
- const progress = i / totalDays;
3424
- if (progress < 0.3) {
3425
- data[i] = Math.floor(Math.random() * 2); // 0-1
3426
- } else if (progress > 0.7) {
3427
- data[i] = Math.floor(Math.random() * 2) + 3; // 3-4
3428
- } else {
3429
- data[i] = Math.floor(Math.random() * 2) + 1; // 1-2
3430
- }
3431
- }
3432
- break;
3433
-
3434
- case 3: // Étudiant orienté vers le succès - Travail régulier
3435
- for (let i = 0; i < totalDays; i++) {
3436
- const weekday = i % 7;
3437
- if (weekday === 5 || weekday === 6) { // Weekend léger
3438
- data[i] = Math.floor(Math.random() * 2); // 0-1
3439
- } else {
3440
- data[i] = Math.floor(Math.random() * 2) + 2; // 2-3
3441
- }
3442
- }
3443
- break;
3444
-
3445
- case 4: // Étudiant motivé - Rythme constant
3446
- for (let i = 0; i < totalDays; i++) {
3447
- const weekday = i % 7;
3448
- if (weekday === 5 || weekday === 6) { // Weekend modéré
3449
- data[i] = Math.floor(Math.random() * 2) + 1; // 1-2
3450
- } else {
3451
- data[i] = Math.floor(Math.random() * 2) + 2; // 2-3
3452
- }
3453
- }
3454
- break;
3455
-
3456
- case 5: // Étudiant surmotivé - Activité intense
3457
- for (let i = 0; i < totalDays; i++) {
3458
- data[i] = Math.floor(Math.random() * 2) + 3; // 3-4
3459
- }
3460
- break;
3461
-
3462
- case 6: // Étudiant stratégique - Efforts ciblés
3463
- for (let i = 0; i < totalDays; i++) {
3464
- const weekday = i % 7;
3465
- if (weekday === 1 || weekday === 3) { // Mardi et jeudi
3466
- data[i] = Math.floor(Math.random() * 2) + 3; // 3-4
3467
- } else {
3468
- data[i] = Math.floor(Math.random() * 2) + 1; // 1-2
3469
- }
3470
- }
3471
- break;
3472
-
3473
- case 7: // Étudiant en amélioration - Progression
3474
- for (let i = 0; i < totalDays; i++) {
3475
- const progress = i / totalDays;
3476
- data[i] = Math.floor(progress * 3) + 1; // 1-4 progressif
3477
  }
3478
- break;
3479
-
3480
- case 8: // Étudiant en difficulté - Irrégulier
3481
- for (let i = 0; i < totalDays; i++) {
3482
- data[i] = Math.random() > 0.6 ? Math.floor(Math.random() * 2) + 1 : 0;
3483
  }
3484
- break;
3485
-
3486
- case 9: // Étudiant évitant l'échec - Minimal
3487
- for (let i = 0; i < totalDays; i++) {
3488
  data[i] = Math.random() > 0.7 ? 1 : 0;
3489
- }
3490
- break;
3491
-
3492
- case 10: // Étudiant à risque - Très irrégulier
3493
- for (let i = 0; i < totalDays; i++) {
3494
  data[i] = Math.random() > 0.8 ? 1 : 0;
3495
  }
3496
- break;
3497
-
3498
- case 11: // Étudiant en progression - Amélioration constante
3499
- for (let i = 0; i < totalDays; i++) {
3500
- const base = Math.floor(i / 7);
3501
- data[i] = Math.min(4, base + Math.floor(Math.random() * 2));
3502
- }
3503
- break;
3504
-
3505
- case 12: // Étudiant acceptant l'échec - Résilient
3506
- for (let i = 0; i < totalDays; i++) {
3507
- data[i] = Math.floor(Math.random() * 3) + 1; // 1-3
3508
- }
3509
- break;
3510
-
3511
- case 13: // Étudiant inactif - Très faible
3512
- for (let i = 0; i < totalDays; i++) {
3513
- data[i] = Math.random() > 0.9 ? 1 : 0;
3514
- }
3515
- break;
3516
-
3517
- case 14: // Étudiant non engagé - Décroissant
3518
- for (let i = 0; i < totalDays; i++) {
3519
- const progress = i / totalDays;
3520
- data[i] = Math.random() > (0.3 + progress * 0.5) ? Math.floor(Math.random() * 2) : 0;
3521
- }
3522
- break;
3523
-
3524
- default:
3525
- for (let i = 0; i < totalDays; i++) {
3526
- data[i] = Math.floor(Math.random() * 5); // 0-4 aléatoire
3527
  }
 
3528
  }
3529
 
3530
  return data;
@@ -3532,62 +3629,8 @@ function generateCompactPersistenceData(scenarioId, totalDays) {
3532
 
3533
  // Analyser les métriques de persévérance compactes
3534
  function analyzeCompactPersistenceMetrics(activityData, scenarioId) {
3535
- const totalDays = activityData.length;
3536
-
3537
- // 1. Calculer la régularité (écart-type)
3538
- const avgActivity = activityData.reduce((a, b) => a + b, 0) / totalDays;
3539
- const variance = activityData.reduce((a, b) => a + Math.pow(b - avgActivity, 2), 0) / totalDays;
3540
- const stdDev = Math.sqrt(variance);
3541
- const regularity = Math.max(0, 100 - stdDev * 25);
3542
-
3543
- // 2. Identifier le schéma d'effort
3544
- let pattern = "Régulier (Effort équilibré toute la semaine)";
3545
- let patternDescription = "Effort équilibré toute la semaine";
3546
-
3547
- // Analyser la distribution
3548
- const weeklyPatterns = [];
3549
- for (let w = 0; w < 4; w++) {
3550
- const weekData = activityData.slice(w * 7, Math.min((w + 1) * 7, totalDays));
3551
- if (weekData.length < 5) continue;
3552
-
3553
- const weekAvg = weekData.reduce((a, b) => a + b, 0) / weekData.length;
3554
-
3555
- if (weekData[4] > weekAvg * 1.5 && weekData[3] > weekAvg * 1.3) {
3556
- pattern = "Effort concentré (Pic d'activité jeudi/vendredi)";
3557
- patternDescription = "Pic d'activité jeudi/vendredi";
3558
- } else if (weekData[0] < weekAvg * 0.7 && weekData[4] > weekAvg * 1.2) {
3559
- pattern = "Accélération progressive (Démarrage lent, fin forte)";
3560
- patternDescription = "Démarrage lent, fin forte";
3561
- } else if (weekData[5] > weekAvg * 1.3 && weekData[6] > weekAvg * 1.3) {
3562
- pattern = "Travail weekend (Activité principalement le weekend)";
3563
- patternDescription = "Activité principalement le weekend";
3564
- } else if (weekAvg < 1) {
3565
- pattern = "Très faible (Activité minimale toute la semaine)";
3566
- patternDescription = "Activité minimale toute la semaine";
3567
- }
3568
- }
3569
-
3570
- // 3. Calculer la gestion des échéances
3571
- const deadlineDays = activityData.filter((_, index) => index % 7 === 3 || index % 7 === 4);
3572
- const nonDeadlineDays = activityData.filter((_, index) => index % 7 !== 3 && index % 7 !== 4);
3573
-
3574
- let deadlineScore = 50;
3575
- if (deadlineDays.length > 0 && nonDeadlineDays.length > 0) {
3576
- const deadlineAvg = deadlineDays.reduce((a, b) => a + b, 0) / deadlineDays.length;
3577
- const nonDeadlineAvg = nonDeadlineDays.reduce((a, b) => a + b, 0) / nonDeadlineDays.length;
3578
- deadlineScore = Math.min(100, Math.max(0, (deadlineAvg / 4) * 100));
3579
- }
3580
-
3581
- // Mettre à jour l'interface compacte
3582
- const regularityScoreElem = document.getElementById("compact-regularityScore");
3583
- const effortPatternElem = document.getElementById("compact-effortPattern");
3584
- const deadlineScoreElem = document.getElementById("compact-deadlineScore");
3585
- const patternTextElem = document.getElementById("compact-patternText");
3586
-
3587
- if (regularityScoreElem) regularityScoreElem.textContent = Math.round(regularity) + "%";
3588
- if (effortPatternElem) effortPatternElem.textContent = pattern;
3589
- if (deadlineScoreElem) deadlineScoreElem.textContent = Math.round(deadlineScore) + "%";
3590
- if (patternTextElem) patternTextElem.textContent = patternDescription;
3591
  }
3592
 
3593
  // ================= RADAR =================
@@ -3601,7 +3644,7 @@ function drawRadar() {
3601
  const ctx = canvas.getContext("2d");
3602
  const cx = canvas.width / 2;
3603
  const cy = canvas.height / 2;
3604
- const radius = Math.min(cx, cy) - 40; // Ajuster selon la taille
3605
  const n = radarMetrics.length;
3606
 
3607
  ctx.clearRect(0, 0, canvas.width, canvas.height);
@@ -3613,8 +3656,7 @@ function drawRadar() {
3613
  ctx.strokeStyle = "#e0e0e0";
3614
  ctx.stroke();
3615
 
3616
- // Ajouter les pourcentages sur les cercles
3617
- if (i % 2 === 0 || i === 1 || i === 5) { // Afficher 0%, 20%, 40%, 60%, 80%, 100%
3618
  const percent = (i * 20) + "%";
3619
  ctx.save();
3620
  ctx.font = "10px Arial";
@@ -3636,7 +3678,6 @@ function drawRadar() {
3636
  ctx.strokeStyle = "#b0bec5";
3637
  ctx.stroke();
3638
 
3639
- // Labels
3640
  const tx = cx + (radius + 25) * Math.cos(angle);
3641
  const ty = cy + (radius + 25) * Math.sin(angle);
3642
 
@@ -3645,7 +3686,6 @@ function drawRadar() {
3645
  ctx.textAlign = angle > Math.PI / 2 || angle < -Math.PI / 2 ? "right" : "left";
3646
  ctx.textBaseline = "middle";
3647
 
3648
- // Raccourcir les labels longs
3649
  let label = m.label;
3650
  if (label.length > 15) {
3651
  label = label.substring(0, 12) + "...";
@@ -3677,29 +3717,24 @@ function drawRadar() {
3677
  const x = cx + r * Math.cos(angle);
3678
  const y = cy + r * Math.sin(angle);
3679
 
3680
- // Dessiner le point
3681
  ctx.beginPath();
3682
  ctx.arc(x, y, 4, 0, 2 * Math.PI);
3683
  ctx.fillStyle = "#1976D2";
3684
  ctx.fill();
3685
 
3686
- // Ajouter le pourcentage à côté du point
3687
  ctx.save();
3688
  ctx.font = "bold 11px Arial";
3689
  ctx.fillStyle = "#1976D2";
3690
  ctx.textAlign = "center";
3691
  ctx.textBaseline = "middle";
3692
 
3693
- // Positionner le pourcentage légèrement décalé
3694
  const labelOffset = 15;
3695
  const labelX = x + labelOffset * Math.cos(angle);
3696
  const labelY = y + labelOffset * Math.sin(angle);
3697
 
3698
- // Ajouter un fond pour une meilleure lisibilité
3699
  ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
3700
  ctx.fillRect(labelX - 15, labelY - 8, 30, 16);
3701
 
3702
- // Écrire le pourcentage
3703
  ctx.fillStyle = "#1976D2";
3704
  ctx.fillText(m.value + "%", labelX, labelY);
3705
  ctx.restore();
@@ -3722,16 +3757,13 @@ function updateNavButtons() {
3722
  function navigateToCrossReading() {
3723
  console.log('Navigation vers la page de lecture croisée...');
3724
 
3725
- // Animation de transition
3726
  const reflectionDiv = document.getElementById('reflection');
3727
  if (reflectionDiv) {
3728
  reflectionDiv.style.opacity = '0.7';
3729
  reflectionDiv.style.transition = 'opacity 0.3s ease';
3730
  }
3731
 
3732
- // Redirection
3733
  setTimeout(() => {
3734
- // Essayer différents chemins pour la page de lecture croisée
3735
  const possiblePaths = [
3736
  'cross_reading/cross_readers.html',
3737
  './cross_reading/cross_readers.html',
@@ -3740,13 +3772,11 @@ function navigateToCrossReading() {
3740
  './cross_readers.html'
3741
  ];
3742
 
3743
- // Vérifier si le fichier existe avant la redirection
3744
  function tryRedirect(index) {
3745
  if (index >= possiblePaths.length) {
3746
  console.error('Page de lecture croisée introuvable');
3747
  showNotification('Erreur', 'Page de lecture croisée introuvable', 'error');
3748
 
3749
- // Restaurer l'opacité
3750
  if (reflectionDiv) {
3751
  reflectionDiv.style.opacity = '1';
3752
  }
@@ -3755,7 +3785,6 @@ function navigateToCrossReading() {
3755
 
3756
  const path = possiblePaths[index];
3757
 
3758
- // Vérifier si le fichier existe (approximation)
3759
  fetch(path, { method: 'HEAD' })
3760
  .then(response => {
3761
  if (response.ok) {
@@ -3777,7 +3806,6 @@ function navigateToCrossReading() {
3777
  function initTrustStars(){
3778
  console.log("Initialisation des étoiles...");
3779
 
3780
- // Réinitialiser toutes les métriques
3781
  for (const key in trustMetrics) {
3782
  trustMetrics[key] = 0;
3783
  }
@@ -3788,16 +3816,13 @@ function initTrustStars(){
3788
  const metric = div.dataset.metric;
3789
  console.log(`Création des étoiles pour: ${metric}`);
3790
 
3791
- // Vérifier que la métrique existe
3792
  if (!trustMetrics.hasOwnProperty(metric)) {
3793
  console.error(`Métrique inconnue: ${metric}`);
3794
  return;
3795
  }
3796
 
3797
- // Vider le conteneur
3798
  div.innerHTML = '';
3799
 
3800
- // Créer 5 étoiles
3801
  for (let i = 1; i <= 5; i++) {
3802
  const star = document.createElement("span");
3803
  star.textContent = "★";
@@ -3805,7 +3830,6 @@ function initTrustStars(){
3805
  star.style.cursor = "pointer";
3806
  star.title = `${i} étoile${i > 1 ? 's' : ''}`;
3807
 
3808
- // Stocker la valeur dans un attribut data
3809
  star.dataset.value = i;
3810
  star.dataset.metric = metric;
3811
 
@@ -3814,10 +3838,8 @@ function initTrustStars(){
3814
  const metric = this.dataset.metric;
3815
  console.log(`Clic sur ${metric}: ${value} étoiles`);
3816
 
3817
- // Mettre à jour la valeur de la métrique
3818
  trustMetrics[metric] = value;
3819
 
3820
- // Mettre à jour l'affichage des étoiles dans ce groupe
3821
  const allStarsInGroup = this.parentElement.children;
3822
  for (let j = 0; j < allStarsInGroup.length; j++) {
3823
  const starElem = allStarsInGroup[j];
@@ -3832,7 +3854,6 @@ function initTrustStars(){
3832
  }
3833
  }
3834
 
3835
- // Mettre à jour la barre de progression
3836
  updateTrustBar();
3837
  };
3838
 
@@ -3852,7 +3873,6 @@ function updateTrustBar(){
3852
  let scoreMaxPossible = 0;
3853
  let details = [];
3854
 
3855
- // Calcul détaillé
3856
  for (const metric in trustMetrics) {
3857
  const valeur = trustMetrics[metric];
3858
  const poids = trustWeights[metric];
@@ -3878,7 +3898,6 @@ function updateTrustBar(){
3878
 
3879
  console.log(`Total: ${scoreTotal.toFixed(2)} / ${scoreMaxPossible.toFixed(2)}`);
3880
 
3881
- // Calcul du pourcentage
3882
  let pourcentage = 0;
3883
  if (scoreMaxPossible > 0) {
3884
  pourcentage = Math.round((scoreTotal / scoreMaxPossible) * 100);
@@ -3886,21 +3905,19 @@ function updateTrustBar(){
3886
 
3887
  console.log(`Pourcentage calculé: ${pourcentage}%`);
3888
 
3889
- // Mettre à jour la barre de progression
3890
  const barre = document.getElementById("trustBar");
3891
  if (barre) {
3892
  barre.style.width = pourcentage + "%";
3893
  barre.textContent = pourcentage + "%";
3894
 
3895
- // Changer la couleur selon le niveau
3896
  if (pourcentage < 40) {
3897
- barre.style.background = "#E53935"; // Rouge - Faible
3898
  barre.title = `Faible confiance (${pourcentage}%)`;
3899
  } else if (pourcentage < 70) {
3900
- barre.style.background = "#FB8C00"; // Orange - Moyen
3901
  barre.title = `Confiance moyenne (${pourcentage}%)`;
3902
  } else {
3903
- barre.style.background = "#43A047"; // Vert - Fort
3904
  barre.title = `Forte confiance (${pourcentage}%)`;
3905
  }
3906
 
@@ -3909,14 +3926,12 @@ function updateTrustBar(){
3909
  console.error("Élément #trustBar non trouvé!");
3910
  }
3911
 
3912
- // Mettre à jour la statistique de confiance moyenne
3913
  const avgTrustElem = document.getElementById("avgTrustScore");
3914
  if (avgTrustElem) {
3915
  avgTrustElem.textContent = pourcentage + "%";
3916
  console.log(`Statistique moyenne mise à jour: ${pourcentage}%`);
3917
  }
3918
 
3919
- // Afficher un résumé dans la console
3920
  console.log("=== RÉSUMÉ FINAL ===");
3921
  console.log(`Indice global de confiance: ${pourcentage}%`);
3922
  console.log("Valeurs des métriques:", JSON.stringify(trustMetrics, null, 2));
@@ -3935,11 +3950,9 @@ function initTrustSave(){
3935
  saveBtn.onclick = () => {
3936
  console.log("=== DÉBUT SAUVEGARDE ===");
3937
 
3938
- // Récupérer les informations GDPR
3939
  const gdprAccept = document.getElementById('gdprAccept').checked;
3940
  const gdprDecline = document.getElementById('gdprDecline').checked;
3941
 
3942
- // Récupérer les informations conditionnelles
3943
  let evaluatorName = "";
3944
  let evaluatorEmail = "";
3945
  let evaluatorRole = "";
@@ -3957,7 +3970,6 @@ function initTrustSave(){
3957
  const comment = document.getElementById("trustComment").value;
3958
  const msgDiv = document.getElementById("saveTrustMsg");
3959
 
3960
- // Validation : consentement GDPR obligatoire
3961
  if (!gdprAccept && !gdprDecline) {
3962
  const message = "❌ Veuillez sélectionner une option de consentement RGPD.";
3963
  console.error(message);
@@ -3970,9 +3982,7 @@ function initTrustSave(){
3970
  return;
3971
  }
3972
 
3973
- // Validation : si GDPR accepté, vérifier les champs obligatoires (seulement les champs marqués *)
3974
  if (gdprAccept) {
3975
- // Seuls les champs avec * sont obligatoires
3976
  if (!evaluatorRole) {
3977
  const message = "❌ Veuillez sélectionner votre rôle.";
3978
  console.error(message);
@@ -4008,11 +4018,8 @@ function initTrustSave(){
4008
  }
4009
  return;
4010
  }
4011
-
4012
- // Note: evaluatorName et evaluatorEmail sont optionnels, pas besoin de validation
4013
  }
4014
 
4015
- // Vérifier si au moins une évaluation
4016
  let hasEvaluation = false;
4017
  for (const metric in trustMetrics) {
4018
  if (trustMetrics[metric] > 0) {
@@ -4033,12 +4040,10 @@ function initTrustSave(){
4033
  return;
4034
  }
4035
 
4036
- // Calculer l'indice de confiance
4037
- const trustScore = updateTrustBar(); // Cette fonction retourne le pourcentage
4038
 
4039
  console.log(`Indice calculé pour sauvegarde: ${trustScore}%`);
4040
 
4041
- // Préparer les données
4042
  const data = {
4043
  timestamp: new Date().toISOString(),
4044
  scenario_id: scenarios[currentScenarioIndex].id,
@@ -4060,7 +4065,6 @@ function initTrustSave(){
4060
 
4061
  console.log("Données à envoyer:", JSON.stringify(data, null, 2));
4062
 
4063
- // Afficher un message de chargement
4064
  if (msgDiv) {
4065
  msgDiv.innerHTML = `
4066
  <div style="display: flex; align-items: center; gap: 10px;">
@@ -4072,18 +4076,15 @@ function initTrustSave(){
4072
  msgDiv.style.color = "#1976D2";
4073
  }
4074
 
4075
- // Envoyer les données vers Google Sheets via le script Apps Script
4076
  fetch(GOOGLE_SCRIPT_URL, {
4077
  method: 'POST',
4078
- mode: 'no-cors', // Important pour les requêtes cross-origin vers Google Apps Script
4079
  headers: {
4080
  'Content-Type': 'application/x-www-form-urlencoded',
4081
  },
4082
  body: new URLSearchParams(data)
4083
  })
4084
  .then(() => {
4085
- // Avec mode: 'no-cors', on ne peut pas lire la réponse
4086
- // On considère que c'est un succès
4087
  console.log("✅ Données envoyées avec succès");
4088
 
4089
  if (msgDiv) {
@@ -4103,7 +4104,6 @@ function initTrustSave(){
4103
  msgDiv.style.padding = "15px";
4104
  }
4105
 
4106
- // Réinitialiser après succès
4107
  setTimeout(() => {
4108
  if (msgDiv) {
4109
  msgDiv.innerHTML = "";
@@ -4137,16 +4137,13 @@ function initTrustSave(){
4137
  console.log("✅ Bouton de sauvegarde initialisé avec Google Sheets");
4138
  }
4139
 
4140
- // Fonction pour réinitialiser l'évaluation
4141
  function resetTrustEvaluation() {
4142
  console.log("Réinitialisation de l'évaluation...");
4143
 
4144
- // Réinitialiser les métriques
4145
  for (const key in trustMetrics) {
4146
  trustMetrics[key] = 0;
4147
  }
4148
 
4149
- // Réinitialiser les étoiles
4150
  document.querySelectorAll(".stars").forEach(div => {
4151
  Array.from(div.children).forEach(star => {
4152
  star.classList.add("inactive");
@@ -4154,10 +4151,8 @@ function resetTrustEvaluation() {
4154
  });
4155
  });
4156
 
4157
- // Réinitialiser la barre
4158
  updateTrustBar();
4159
 
4160
- // Vider le commentaire
4161
  const commentField = document.getElementById("trustComment");
4162
  if (commentField) {
4163
  commentField.value = "";
@@ -4168,7 +4163,6 @@ function resetTrustEvaluation() {
4168
 
4169
  // ================= FONCTIONS UTILITAIRES =================
4170
 
4171
- // Mettre à jour les statistiques
4172
  function updateStats(scenario) {
4173
  if (!scenario) return;
4174
 
@@ -4180,7 +4174,6 @@ function updateStats(scenario) {
4180
  currentScenarioNum.textContent = scenario.id || "-";
4181
  }
4182
 
4183
- // Niveau de risque
4184
  if (riskLevelElem) {
4185
  const risk = scenario.risk || 50;
4186
  let riskLevel = "Moyen";
@@ -4198,25 +4191,19 @@ function updateStats(scenario) {
4198
  riskLevelElem.style.color = riskColor;
4199
  }
4200
 
4201
- // Activité moyenne à partir des données radar
4202
  if (avgActivityElem && scenario.radar && scenario.radar.length > 0) {
4203
- // Filtrer pour enlever "Engagement global" si présent
4204
  const filteredRadar = scenario.radar.filter(metric => metric.label !== "Engagement global");
4205
  const avgRadar = filteredRadar.reduce((sum, item) => sum + item.value, 0) / filteredRadar.length;
4206
  avgActivityElem.textContent = Math.round(avgRadar) + "%";
4207
  }
4208
  }
4209
 
4210
- // Fonction pour remplir un exemple d'évaluateur
4211
  function fillSampleEvaluator() {
4212
- // Sélectionner l'option GDPR "accept"
4213
  document.getElementById('gdprAccept').checked = true;
4214
  document.getElementById('gdprDecline').checked = false;
4215
 
4216
- // Mettre à jour les champs
4217
  initGDPR();
4218
 
4219
- // Remplir les champs
4220
  document.getElementById("evaluatorName").value = "Martin Sophie";
4221
  document.getElementById("evaluatorEmail").value = "sophie.martin@exemple.fr";
4222
  document.getElementById("evaluatorRole").value = "enseignant";
@@ -4226,19 +4213,15 @@ function fillSampleEvaluator() {
4226
  showNotification("Exemple", "Champs d'évaluateur remplis avec un exemple", "info");
4227
  }
4228
 
4229
- // Fonction pour effacer les champs évaluateur
4230
  function clearEvaluatorFields() {
4231
- // Sélectionner l'option GDPR "decline" par défaut
4232
  document.getElementById('gdprDecline').checked = true;
4233
  document.getElementById('gdprAccept').checked = false;
4234
 
4235
- // Mettre à jour les champs
4236
  initGDPR();
4237
 
4238
  showNotification("Champs effacés", "Les informations d'évaluateur ont été effacées", "info");
4239
  }
4240
 
4241
- // Fonction pour afficher une notification
4242
  function showNotification(title, message, type = "info") {
4243
  console.log(`[${type}] ${title}: ${message}`);
4244
 
@@ -4250,7 +4233,6 @@ function showNotification(title, message, type = "info") {
4250
  msgDiv.style.color = type === "success" ? "#2E7D32" :
4251
  type === "error" ? "#C62828" : "#1565C0";
4252
 
4253
- // Effacer après 5 secondes
4254
  setTimeout(() => {
4255
  msgDiv.textContent = "";
4256
  msgDiv.style.background = "";
@@ -4259,7 +4241,6 @@ function showNotification(title, message, type = "info") {
4259
  }
4260
  }
4261
 
4262
- // Changer le mode d'analyse de persévérance
4263
  function changePersistenceAnalysis() {
4264
  const modeSelect = document.getElementById("persistenceMode");
4265
  if (!modeSelect) return;
@@ -4269,32 +4250,9 @@ function changePersistenceAnalysis() {
4269
 
4270
  if (!currentScenario) return;
4271
 
4272
- // Redessiner la heatmap avec le mode sélectionné
4273
  drawCompactEnrichedHeatmapWithAxes(currentScenario);
4274
 
4275
- // Ajouter une annotation selon le mode
4276
- const canvas = document.getElementById("heatmap");
4277
- if (!canvas) return;
4278
-
4279
- const ctx = canvas.getContext("2d");
4280
-
4281
- // Effacer l'annotation précédente
4282
- ctx.clearRect(0, canvas.height - 30, canvas.width, 30);
4283
-
4284
- ctx.font = "12px Arial";
4285
- ctx.fillStyle = "#1976D2";
4286
- ctx.textAlign = "center";
4287
-
4288
- switch(mode) {
4289
- case "regularity":
4290
- break;
4291
- case "effortPattern":
4292
- break;
4293
- case "deadline":
4294
- break;
4295
- case "combined":
4296
- break;
4297
- }
4298
  }
4299
 
4300
  // Exposer les fonctions globales
 
468
 
469
  .compact-competences-grid {
470
  display: grid;
471
+ grid-template-columns: repeat(4, 1fr);
472
+ grid-template-rows: repeat(3, auto);
473
  gap: 10px;
474
  margin: 10px 0;
475
  }
476
 
 
477
  .compact-competence-matrix-item {
478
  padding: 1px;
479
  background: linear-gradient(135deg, #f8f9fa, #e9ecef);
 
493
  background: linear-gradient(135deg, #e3f2fd, #bbdefb);
494
  }
495
 
 
496
  .compact-matrix-competence-label {
497
  font-size: 12px;
498
  font-weight: 600;
 
2044
  <span>🕖</span> Indicateurs de la gestion du temps et régularité
2045
  </h5>
2046
  <div class="compact-persistence-indicators">
2047
+ <div class="compact-indicator" id="regularity-indicator">
2048
  <span class="compact-indicator-dot" style="background:#FF6B6B;"></span>
2049
  <span>
2050
  Régularité du travail :
 
2052
  </span>
2053
  </div>
2054
 
2055
+ <div style="margin-left: 18px; margin-top: 0; font-size: 12px; color: #888;" id="regularity-description">
2056
  La constance de l'activité de l'apprenant dans le temps.
2057
  </div>
2058
 
2059
+ <div class="compact-indicator" id="deadline-indicator">
2060
  <span class="compact-indicator-dot" style="background:#FFD166;"></span>
2061
  <span>Gestion des échéances : <strong id="compact-deadlineScore">-</strong></span>
2062
  </div>
2063
 
2064
+ <div style="margin-left: 18px; margin-top: 0; font-size: 12px; color: #888;" id="deadline-description">
2065
  La capacité de l'apprenant à respecter les délais.
2066
  </div>
2067
 
2068
+ <div class="compact-indicator" style="margin-top: 10px;" id="effort-indicator">
2069
  <span class="compact-indicator-dot" style="background:#4ECDC4;"></span>
2070
  <span>
2071
  <strong>Schéma d'effort :</strong>
2072
+ <span id="compact-effortPattern">-</span>
2073
  </span>
2074
  </div>
2075
 
2076
+ <div style="margin-left: 18px; margin-top: 0; font-size: 12px; color: #888;" id="effort-description">
2077
  La dynamique temporelle de l'effort.
2078
  </div>
2079
  </div>
 
2343
  // URL du script Google Apps Script pour la sauvegarde
2344
  const GOOGLE_SCRIPT_URL = 'https://script.google.com/macros/s/AKfycbyB_Q1RH9IctsE_jEbZUmyxv4WXlpGFFgtyEUsLmV72W3htK1YO3GSeoyjQIoWCKEod/exec';
2345
 
2346
+ // SCÉNARIOS PAR DÉFAUT (16 profils)
2347
  const DEFAULT_SCENARIOS = [
2348
  { id: 1, title: "Étudiant engagé", manifest: { type: "Engagement élevé", manifeste: "Je suis très motivé et j'essaie de faire toutes les activités", description: "Étudiant avec un fort engagement et une régularité dans le travail" } },
2349
  { id: 2, title: "Étudiant actif mais inefficace", manifest: { type: "Activité désorganisée", manifeste: "Je travaille beaucoup mais je ne vois pas les résultats", description: "Beaucoup d'effort mais peu de résultats concrets" } },
 
2358
  { id: 11, title: "Étudiant en progression", manifest: { type: "Amélioration technique", manifeste: "Mes compétences techniques s'améliorent régulièrement", description: "Développement progressif des compétences techniques" } },
2359
  { id: 12, title: "Étudiant acceptant l'échec", manifest: { type: "Résilience", manifeste: "Je vois l'échec comme une opportunité d'apprendre", description: "Attitude positive face aux erreurs et échecs" } },
2360
  { id: 13, title: "Étudiant inactif", manifest: { type: "Inactivité", manifeste: "Je ne trouve pas la motivation pour commencer", description: "Très faible participation et engagement" } },
2361
+ { id: 14, title: "Étudiant non engagé", manifest: { type: "Désengagement", manifeste: "Ce cours ne m'intéresse pas vraiment", description: "Manque d'intérêt et d'implication" } },
2362
+ { id: 15, title: "Étudiant persévérant", manifest: { type: "Persévérance", manifeste: "Je continue malgré les difficultés", description: "Efforts maintenus malgré les doutes" } },
2363
+ { id: 16, title: "Étudiant actif", manifest: { type: "Actif", manifeste: "Je suis très actif sur la plateforme", description: "Forte implication et nombreux efforts" } }
2364
  ];
2365
 
2366
  // MAPPING PERSÉVÉRANCE PAR PROFIL
 
2368
  "Étudiant engagé": {
2369
  level: "Très élevée",
2370
  interpretation: "Efforts constants, persévère même face aux difficultés",
2371
+ color: "#43A047",
2372
+ regularity: 90,
2373
+ deadline: 88,
2374
+ effortPattern: "Effort concentré (Pic d'activité jeudi/vendredi)"
2375
  },
2376
  "Étudiant actif mais inefficace": {
2377
  level: "Moyenne",
2378
  interpretation: "Efforts importants mais mal régulés, persévérance peu productive",
2379
+ color: "#FB8C00",
2380
+ regularity: 55,
2381
+ deadline: 44,
2382
+ effortPattern: "Travail weekend (Activité principalement le weekend)"
2383
  },
2384
  "Étudiant orienté vers le succès": {
2385
  level: "Élevée",
2386
  interpretation: "Persévérance principalement guidée par l'atteinte des objectifs",
2387
+ color: "#4CAF50",
2388
+ regularity: 75,
2389
+ deadline: 66,
2390
+ effortPattern: "Régulier (Effort équilibré toute la semaine)"
2391
  },
2392
  "Étudiant motivé": {
2393
  level: "Élevée",
2394
  interpretation: "Engagement soutenu et continuité stable de l'effort",
2395
+ color: "#4CAF50",
2396
+ regularity: 75,
2397
+ deadline: 66,
2398
+ effortPattern: "Régulier (Effort équilibré toute la semaine)"
2399
  },
2400
  "Étudiant surmotivé": {
2401
  level: "Très élevée",
2402
  interpretation: "Effort intense, parfois excessif, avec risque de surcharge",
2403
+ color: "#43A047",
2404
+ regularity: 90,
2405
+ deadline: 91,
2406
+ effortPattern: "Régulier (Effort équilibré toute la semaine)"
2407
  },
2408
  "Étudiant stratégique": {
2409
  level: "Élevée",
2410
  interpretation: "Effort bien dosé, persévérance optimisée selon le rendement attendu",
2411
+ color: "#4CAF50",
2412
+ regularity: 75,
2413
+ deadline: 66,
2414
+ effortPattern: "Régulier (Effort équilibré toute la semaine)"
2415
  },
2416
  "Étudiant en amélioration": {
2417
  level: "Moyenne à élevée",
2418
  interpretation: "Efforts croissants, persévérance en cours de structuration",
2419
+ color: "#FF9800",
2420
+ regularity: 55,
2421
+ deadline: 50,
2422
+ effortPattern: "Travail weekend (Activité principalement le weekend)"
2423
  },
2424
  "Étudiant en difficulté": {
2425
  level: "Faible",
2426
  interpretation: "Découragement fréquent et difficulté à maintenir l'effort",
2427
+ color: "#E53935",
2428
+ regularity: 35,
2429
+ deadline: 13,
2430
+ effortPattern: "Très faible (Activité minimale toute la semaine)"
2431
  },
2432
  "Étudiant évitant l'échec": {
2433
  level: "Moyenne",
2434
  interpretation: "Persévérance motivée par la peur de l'échec plutôt que par l'apprentissage",
2435
+ color: "#FB8C00",
2436
+ regularity: 55,
2437
+ deadline: 19,
2438
+ effortPattern: "Effort concentré (Pic d'activité jeudi/vendredi)"
2439
  },
2440
  "Étudiant à risque": {
2441
  level: "Très faible",
2442
  interpretation: "Abandon rapide et très faible tolérance à l'effort",
2443
+ color: "#C62828",
2444
+ regularity: 20,
2445
+ deadline: 9,
2446
+ effortPattern: "Très faible (Activité minimale toute la semaine)"
2447
  },
2448
  "Étudiant en progression": {
2449
  level: "Élevée",
2450
  interpretation: "Efforts réguliers et de mieux en mieux maîtrisés",
2451
+ color: "#4CAF50",
2452
+ regularity: 75,
2453
+ deadline: 47,
2454
+ effortPattern: "Très faible (Activité minimale toute la semaine)"
2455
  },
2456
  "Étudiant acceptant l'échec": {
2457
  level: "Élevée",
2458
  interpretation: "Bonne résilience, persévère malgré les erreurs et les échecs",
2459
+ color: "#4CAF50",
2460
+ regularity: 75,
2461
+ deadline: 47,
2462
+ effortPattern: "Régulier (Effort équilibré toute la semaine)"
2463
  },
2464
  "Étudiant inactif": {
2465
  level: "Très faible",
2466
  interpretation: "Manque d'engagement, difficulté à initier et maintenir l'effort",
2467
+ color: "#C62828",
2468
+ regularity: 20,
2469
+ deadline: 0,
2470
+ effortPattern: "Très faible (Activité minimale toute la semaine)"
2471
  },
2472
  "Étudiant non engagé": {
2473
  level: "Faible",
2474
  interpretation: "Manque de motivation, faible persévérance dans l'effort",
2475
+ color: "#E53935",
2476
+ regularity: 35,
2477
+ deadline: 3,
2478
+ effortPattern: "Très faible (Activité minimale toute la semaine)"
2479
  },
2480
  "Étudiant persévérant": {
2481
+ level: "Moyenne à élevée",
2482
+ interpretation: "Efforts maintenus malgré les doutes, persévérance réelle mais freinée par le manque de confiance",
2483
+ color: "#FF9800",
2484
+ regularity: 55,
2485
+ deadline: 56,
2486
+ effortPattern: "Accélération progressive (Démarrage lent, fin forte)"
2487
+ },
2488
+ "Étudiant actif": {
2489
+ level: "Élevée",
2490
+ interpretation: "Forte implication et nombreux efforts, mais difficulté à maintenir l'énergie jusqu'au bout",
2491
+ color: "#4CAF50",
2492
+ regularity: 75,
2493
+ deadline: 41,
2494
+ effortPattern: "Régulier (Effort équilibré toute la semaine)"
2495
+ }
2496
  };
2497
 
2498
+ // Messages de profils complets (16 profils)
2499
  const profileMessages = {
2500
  "Étudiant engagé": {
2501
  title: "Démarrage Rapide & Engagement Soutenu",
 
2624
  ]
2625
  },
2626
  "Étudiant persévérant": {
2627
+ title: "Efforts Réels malgré le Doute",
2628
+ message: "Tu avances avec persévérance malgré des doutes sur toi-même. Tu démarres 55% des activités et en termines 58%. Tes résultats montrent que tes capacités sont bien là, même si tu hésites encore à te faire confiance.",
2629
+ insights: [
2630
+ { icon: "🌱", text: "Efforts constants malgré les doutes" },
2631
+ { icon: "🧠", text: "Compétences bien présentes (66%)" },
2632
+ { icon: "💪", text: "Persévérance visible" }
2633
+ ]
2634
+ },
2635
+ "Étudiant actif": {
2636
+ title: "Engagement Fort mais Énergie à Préserver",
2637
+ message: "Tu démarres beaucoup d'activités (85%) et tu t'appuies largement sur les ressources (75%). Cet engagement montre ta motivation, mais il rend parfois difficile l'achèvement des tâches (45%). Mieux répartir tes efforts t'aidera à avancer plus sereinement.",
2638
+ insights: [
2639
+ { icon: "⚡", text: "Engagement élevé dès le départ (85%)" },
2640
+ { icon: "📚", text: "Usage fréquent des ressources (75%)" },
2641
+ { icon: "🧘", text: "Besoin de mieux doser l'effort" }
2642
+ ]
2643
+ }
2644
  };
2645
 
2646
  // ================= INIT =================
 
2747
  function tryLoad(pathIndex) {
2748
  if (pathIndex >= possiblePaths.length) {
2749
  console.error("❌ Impossible de charger les scénarios depuis aucun chemin");
2750
+ console.log("Utilisation des scénarios par défaut (16 profils)");
2751
  scenarios = generateDefaultScenarios();
2752
 
2753
  if (scenarios.length === 0) {
 
2790
 
2791
  // Générer les scénarios par défaut
2792
  function generateDefaultScenarios() {
2793
+ console.log("Génération des 16 scénarios par défaut");
2794
 
2795
  const defaultScenarios = [...DEFAULT_SCENARIOS];
2796
 
 
2883
  case "Étudiant non engagé":
2884
  baseValues = [30, 35, 32, 75, 25, 40, 38];
2885
  break;
2886
+ case "Étudiant persévérant":
2887
+ baseValues = [55, 65, 64, 68, 58, 60, 66];
2888
+ break;
2889
+ case "Étudiant actif":
2890
+ baseValues = [85, 62, 60, 58, 45, 75, 63];
2891
+ break;
2892
  default:
2893
  baseValues = [70, 65, 62, 50, 65, 70, 68];
2894
  }
 
2918
  "Étudiant inactif": "Le premier pas est le plus difficile. Choisis une seule activité simple pour commencer, sans pression.",
2919
  "Étudiant non engagé": "Il est normal de manquer d'intérêt parfois. Cherche un aspect du cours qui pourrait te motiver davantage.",
2920
  "Étudiant persévérant": "Tes compétences sont solides. Fais confiance à ton potentiel et ose t'investir pleinement.",
2921
+ "Étudiant actif": "Ton engagement est fort mais attention à ne pas t'épuiser. Apprends à mieux doser tes efforts."
2922
  };
2923
 
2924
  return messages[profileTitle] || "Analyse de votre profil d'apprentissage en cours...";
 
2940
  "Étudiant en progression": 40,
2941
  "Étudiant acceptant l'échec": 55,
2942
  "Étudiant inactif": 90,
2943
+ "Étudiant non engagé": 75,
2944
+ "Étudiant persévérant": 45,
2945
+ "Étudiant actif": 60
2946
  };
2947
 
2948
  return riskLevels[profileTitle] || 50;
 
3312
  title: "Désengagement",
3313
  emoji: "😑",
3314
  pattern: "Activité sporadique et décroissante"
3315
+ },
3316
+ 15: {
3317
+ title: "Persévérant malgré le doute",
3318
+ emoji: "🌱",
3319
+ pattern: "Accélération progressive en fin de semaine"
3320
+ },
3321
+ 16: {
3322
+ title: "Actif mais à risque d'épuisement",
3323
+ emoji: "⚡",
3324
+ pattern: "Forte activité en début de semaine"
3325
  }
3326
  };
3327
 
 
3414
 
3415
  // Analyser et afficher les métriques de persévérance compactes
3416
  analyzeCompactPersistenceMetrics(activityData, scenario.id);
3417
+
3418
+ // Mettre à jour les indicateurs selon le mode sélectionné
3419
+ const currentMode = document.getElementById("persistenceMode").value;
3420
+ updatePersistenceIndicators(currentMode);
3421
+ }
3422
+
3423
+ // Mettre à jour les indicateurs selon le mode d'analyse
3424
+ function updatePersistenceIndicators(mode) {
3425
+ // Récupérer les éléments
3426
+ const regularityIndicator = document.getElementById("regularity-indicator");
3427
+ const regularityDesc = document.getElementById("regularity-description");
3428
+ const deadlineIndicator = document.getElementById("deadline-indicator");
3429
+ const deadlineDesc = document.getElementById("deadline-description");
3430
+ const effortIndicator = document.getElementById("effort-indicator");
3431
+ const effortDesc = document.getElementById("effort-description");
3432
+
3433
+ const regularityScore = document.getElementById("compact-regularityScore");
3434
+ const deadlineScore = document.getElementById("compact-deadlineScore");
3435
+ const effortPattern = document.getElementById("compact-effortPattern");
3436
+ const regularityText = document.getElementById("compact-regularityText");
3437
+
3438
+ if (!regularityIndicator || !deadlineIndicator || !effortIndicator) return;
3439
+
3440
+ // Réinitialiser l'affichage (tout masquer par défaut)
3441
+ regularityIndicator.style.display = "none";
3442
+ regularityDesc.style.display = "none";
3443
+ deadlineIndicator.style.display = "none";
3444
+ deadlineDesc.style.display = "none";
3445
+ effortIndicator.style.display = "none";
3446
+ effortDesc.style.display = "none";
3447
+
3448
+ const currentScenario = scenarios[currentScenarioIndex];
3449
+ if (!currentScenario) return;
3450
+
3451
+ const profile = perseveranceProfiles[currentScenario.title];
3452
+
3453
+ switch(mode) {
3454
+ case "regularity":
3455
+ // Afficher seulement la régularité
3456
+ regularityIndicator.style.display = "flex";
3457
+ regularityDesc.style.display = "block";
3458
+
3459
+ if (regularityText) {
3460
+ regularityText.innerHTML = `
3461
+ <div style="font-size: 12px; color: #555; line-height: 1.4;">
3462
+ <strong>Analyse de la régularité du travail</strong><br>
3463
+ ${profile ? profile.interpretation : "La constance de l'activité de l'apprenant dans le temps."}
3464
+ </div>
3465
+ `;
3466
+ }
3467
+ break;
3468
+
3469
+ case "deadline":
3470
+ // Afficher seulement la gestion des échéances
3471
+ deadlineIndicator.style.display = "flex";
3472
+ deadlineDesc.style.display = "block";
3473
+
3474
+ if (regularityText) {
3475
+ regularityText.innerHTML = `
3476
+ <div style="font-size: 12px; color: #555; line-height: 1.4;">
3477
+ <strong>Analyse de la gestion des échéances</strong><br>
3478
+ Capacité à respecter les délais et à organiser le travail avant les dates limites.
3479
+ </div>
3480
+ `;
3481
+ }
3482
+ break;
3483
+
3484
+ case "effortPattern":
3485
+ // Afficher seulement le schéma d'effort
3486
+ effortIndicator.style.display = "flex";
3487
+ effortDesc.style.display = "block";
3488
+
3489
+ if (regularityText) {
3490
+ regularityText.innerHTML = `
3491
+ <div style="font-size: 12px; color: #555; line-height: 1.4;">
3492
+ <strong>Analyse du schéma d'effort</strong><br>
3493
+ La dynamique temporelle de l'effort et la distribution de l'activité.
3494
+ </div>
3495
+ `;
3496
+ }
3497
+ break;
3498
+
3499
+ case "combined":
3500
+ // Afficher tous les indicateurs
3501
+ regularityIndicator.style.display = "flex";
3502
+ regularityDesc.style.display = "block";
3503
+ deadlineIndicator.style.display = "flex";
3504
+ deadlineDesc.style.display = "block";
3505
+ effortIndicator.style.display = "flex";
3506
+ effortDesc.style.display = "block";
3507
+
3508
+ if (regularityText) {
3509
+ regularityText.innerHTML = `
3510
+ <div style="font-size: 12px; color: #555; line-height: 1.4;">
3511
+ <strong>Vue combinée</strong><br>
3512
+ ${profile ? profile.interpretation : "Analyse complète de la persévérance et de la gestion des efforts."}
3513
+ </div>
3514
+ `;
3515
+ }
3516
+ break;
3517
+
3518
+ default:
3519
+ // Par défaut, tout afficher
3520
+ regularityIndicator.style.display = "flex";
3521
+ regularityDesc.style.display = "block";
3522
+ deadlineIndicator.style.display = "flex";
3523
+ deadlineDesc.style.display = "block";
3524
+ effortIndicator.style.display = "flex";
3525
+ effortDesc.style.display = "block";
3526
+ }
3527
  }
3528
 
3529
  // Mettre à jour la persévérance spécifique au profil
 
3545
  return;
3546
  }
3547
 
3548
+ // Mettre à jour l'interface avec les valeurs spécifiques
3549
+ const regularityScore = document.getElementById("compact-regularityScore");
3550
+ const deadlineScore = document.getElementById("compact-deadlineScore");
3551
+ const effortPattern = document.getElementById("compact-effortPattern");
3552
  const regularityText = document.getElementById("compact-regularityText");
3553
+
3554
+ if (regularityScore) {
3555
+ regularityScore.textContent = profile.regularity + "%";
3556
+ regularityScore.style.color = profile.color;
3557
+ }
3558
+
3559
+ if (deadlineScore) {
3560
+ deadlineScore.textContent = profile.deadline + "%";
3561
+ deadlineScore.style.color = profile.color;
3562
+ }
3563
+
3564
+ if (effortPattern) {
3565
+ effortPattern.textContent = profile.effortPattern;
3566
+ effortPattern.style.color = profile.color;
3567
+ }
3568
+
3569
  if (regularityText) {
3570
  regularityText.innerHTML = `
3571
  <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 5px;">
 
3577
  </div>
3578
  `;
3579
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3580
  }
3581
 
3582
  // Générer des données de persévérance compactes
3583
  function generateCompactPersistenceData(scenarioId, totalDays) {
3584
  const data = new Array(totalDays).fill(0);
3585
 
3586
+ // Utiliser les valeurs du profil pour générer des données cohérentes
3587
+ const profile = Object.values(perseveranceProfiles)[scenarioId - 1] || perseveranceProfiles["Étudiant engagé"];
3588
+
3589
+ for (let i = 0; i < totalDays; i++) {
3590
+ const weekday = i % 7;
3591
+ const week = Math.floor(i / 7);
3592
+ const progress = i / totalDays;
3593
+
3594
+ // Adapter les données selon le schéma d'effort du profil
3595
+ if (profile.effortPattern.includes("Pic d'activité jeudi/vendredi")) {
3596
+ if (weekday === 3 || weekday === 4) {
3597
+ data[i] = 4;
3598
+ } else if (weekday === 5 || weekday === 6) {
3599
+ data[i] = 1;
3600
+ } else {
3601
+ data[i] = 2;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3602
  }
3603
+ } else if (profile.effortPattern.includes("Travail weekend")) {
3604
+ if (weekday === 5 || weekday === 6) {
3605
+ data[i] = 4;
3606
+ } else {
3607
+ data[i] = 2;
3608
  }
3609
+ } else if (profile.effortPattern.includes("Accélération progressive")) {
3610
+ data[i] = Math.min(4, Math.floor(progress * 4) + 1);
3611
+ } else if (profile.effortPattern.includes("Activité minimale")) {
3612
+ if (week === 0) {
3613
  data[i] = Math.random() > 0.7 ? 1 : 0;
3614
+ } else {
 
 
 
 
3615
  data[i] = Math.random() > 0.8 ? 1 : 0;
3616
  }
3617
+ } else {
3618
+ // Régulier
3619
+ if (weekday === 5 || weekday === 6) {
3620
+ data[i] = 2;
3621
+ } else {
3622
+ data[i] = 3;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3623
  }
3624
+ }
3625
  }
3626
 
3627
  return data;
 
3629
 
3630
  // Analyser les métriques de persévérance compactes
3631
  function analyzeCompactPersistenceMetrics(activityData, scenarioId) {
3632
+ // Cette fonction est maintenant remplacée par les valeurs prédéfinies dans updatePerseveranceProfile
3633
+ // On ne fait rien ici pour éviter d'écraser les valeurs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3634
  }
3635
 
3636
  // ================= RADAR =================
 
3644
  const ctx = canvas.getContext("2d");
3645
  const cx = canvas.width / 2;
3646
  const cy = canvas.height / 2;
3647
+ const radius = Math.min(cx, cy) - 40;
3648
  const n = radarMetrics.length;
3649
 
3650
  ctx.clearRect(0, 0, canvas.width, canvas.height);
 
3656
  ctx.strokeStyle = "#e0e0e0";
3657
  ctx.stroke();
3658
 
3659
+ if (i % 2 === 0 || i === 1 || i === 5) {
 
3660
  const percent = (i * 20) + "%";
3661
  ctx.save();
3662
  ctx.font = "10px Arial";
 
3678
  ctx.strokeStyle = "#b0bec5";
3679
  ctx.stroke();
3680
 
 
3681
  const tx = cx + (radius + 25) * Math.cos(angle);
3682
  const ty = cy + (radius + 25) * Math.sin(angle);
3683
 
 
3686
  ctx.textAlign = angle > Math.PI / 2 || angle < -Math.PI / 2 ? "right" : "left";
3687
  ctx.textBaseline = "middle";
3688
 
 
3689
  let label = m.label;
3690
  if (label.length > 15) {
3691
  label = label.substring(0, 12) + "...";
 
3717
  const x = cx + r * Math.cos(angle);
3718
  const y = cy + r * Math.sin(angle);
3719
 
 
3720
  ctx.beginPath();
3721
  ctx.arc(x, y, 4, 0, 2 * Math.PI);
3722
  ctx.fillStyle = "#1976D2";
3723
  ctx.fill();
3724
 
 
3725
  ctx.save();
3726
  ctx.font = "bold 11px Arial";
3727
  ctx.fillStyle = "#1976D2";
3728
  ctx.textAlign = "center";
3729
  ctx.textBaseline = "middle";
3730
 
 
3731
  const labelOffset = 15;
3732
  const labelX = x + labelOffset * Math.cos(angle);
3733
  const labelY = y + labelOffset * Math.sin(angle);
3734
 
 
3735
  ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
3736
  ctx.fillRect(labelX - 15, labelY - 8, 30, 16);
3737
 
 
3738
  ctx.fillStyle = "#1976D2";
3739
  ctx.fillText(m.value + "%", labelX, labelY);
3740
  ctx.restore();
 
3757
  function navigateToCrossReading() {
3758
  console.log('Navigation vers la page de lecture croisée...');
3759
 
 
3760
  const reflectionDiv = document.getElementById('reflection');
3761
  if (reflectionDiv) {
3762
  reflectionDiv.style.opacity = '0.7';
3763
  reflectionDiv.style.transition = 'opacity 0.3s ease';
3764
  }
3765
 
 
3766
  setTimeout(() => {
 
3767
  const possiblePaths = [
3768
  'cross_reading/cross_readers.html',
3769
  './cross_reading/cross_readers.html',
 
3772
  './cross_readers.html'
3773
  ];
3774
 
 
3775
  function tryRedirect(index) {
3776
  if (index >= possiblePaths.length) {
3777
  console.error('Page de lecture croisée introuvable');
3778
  showNotification('Erreur', 'Page de lecture croisée introuvable', 'error');
3779
 
 
3780
  if (reflectionDiv) {
3781
  reflectionDiv.style.opacity = '1';
3782
  }
 
3785
 
3786
  const path = possiblePaths[index];
3787
 
 
3788
  fetch(path, { method: 'HEAD' })
3789
  .then(response => {
3790
  if (response.ok) {
 
3806
  function initTrustStars(){
3807
  console.log("Initialisation des étoiles...");
3808
 
 
3809
  for (const key in trustMetrics) {
3810
  trustMetrics[key] = 0;
3811
  }
 
3816
  const metric = div.dataset.metric;
3817
  console.log(`Création des étoiles pour: ${metric}`);
3818
 
 
3819
  if (!trustMetrics.hasOwnProperty(metric)) {
3820
  console.error(`Métrique inconnue: ${metric}`);
3821
  return;
3822
  }
3823
 
 
3824
  div.innerHTML = '';
3825
 
 
3826
  for (let i = 1; i <= 5; i++) {
3827
  const star = document.createElement("span");
3828
  star.textContent = "★";
 
3830
  star.style.cursor = "pointer";
3831
  star.title = `${i} étoile${i > 1 ? 's' : ''}`;
3832
 
 
3833
  star.dataset.value = i;
3834
  star.dataset.metric = metric;
3835
 
 
3838
  const metric = this.dataset.metric;
3839
  console.log(`Clic sur ${metric}: ${value} étoiles`);
3840
 
 
3841
  trustMetrics[metric] = value;
3842
 
 
3843
  const allStarsInGroup = this.parentElement.children;
3844
  for (let j = 0; j < allStarsInGroup.length; j++) {
3845
  const starElem = allStarsInGroup[j];
 
3854
  }
3855
  }
3856
 
 
3857
  updateTrustBar();
3858
  };
3859
 
 
3873
  let scoreMaxPossible = 0;
3874
  let details = [];
3875
 
 
3876
  for (const metric in trustMetrics) {
3877
  const valeur = trustMetrics[metric];
3878
  const poids = trustWeights[metric];
 
3898
 
3899
  console.log(`Total: ${scoreTotal.toFixed(2)} / ${scoreMaxPossible.toFixed(2)}`);
3900
 
 
3901
  let pourcentage = 0;
3902
  if (scoreMaxPossible > 0) {
3903
  pourcentage = Math.round((scoreTotal / scoreMaxPossible) * 100);
 
3905
 
3906
  console.log(`Pourcentage calculé: ${pourcentage}%`);
3907
 
 
3908
  const barre = document.getElementById("trustBar");
3909
  if (barre) {
3910
  barre.style.width = pourcentage + "%";
3911
  barre.textContent = pourcentage + "%";
3912
 
 
3913
  if (pourcentage < 40) {
3914
+ barre.style.background = "#E53935";
3915
  barre.title = `Faible confiance (${pourcentage}%)`;
3916
  } else if (pourcentage < 70) {
3917
+ barre.style.background = "#FB8C00";
3918
  barre.title = `Confiance moyenne (${pourcentage}%)`;
3919
  } else {
3920
+ barre.style.background = "#43A047";
3921
  barre.title = `Forte confiance (${pourcentage}%)`;
3922
  }
3923
 
 
3926
  console.error("Élément #trustBar non trouvé!");
3927
  }
3928
 
 
3929
  const avgTrustElem = document.getElementById("avgTrustScore");
3930
  if (avgTrustElem) {
3931
  avgTrustElem.textContent = pourcentage + "%";
3932
  console.log(`Statistique moyenne mise à jour: ${pourcentage}%`);
3933
  }
3934
 
 
3935
  console.log("=== RÉSUMÉ FINAL ===");
3936
  console.log(`Indice global de confiance: ${pourcentage}%`);
3937
  console.log("Valeurs des métriques:", JSON.stringify(trustMetrics, null, 2));
 
3950
  saveBtn.onclick = () => {
3951
  console.log("=== DÉBUT SAUVEGARDE ===");
3952
 
 
3953
  const gdprAccept = document.getElementById('gdprAccept').checked;
3954
  const gdprDecline = document.getElementById('gdprDecline').checked;
3955
 
 
3956
  let evaluatorName = "";
3957
  let evaluatorEmail = "";
3958
  let evaluatorRole = "";
 
3970
  const comment = document.getElementById("trustComment").value;
3971
  const msgDiv = document.getElementById("saveTrustMsg");
3972
 
 
3973
  if (!gdprAccept && !gdprDecline) {
3974
  const message = "❌ Veuillez sélectionner une option de consentement RGPD.";
3975
  console.error(message);
 
3982
  return;
3983
  }
3984
 
 
3985
  if (gdprAccept) {
 
3986
  if (!evaluatorRole) {
3987
  const message = "❌ Veuillez sélectionner votre rôle.";
3988
  console.error(message);
 
4018
  }
4019
  return;
4020
  }
 
 
4021
  }
4022
 
 
4023
  let hasEvaluation = false;
4024
  for (const metric in trustMetrics) {
4025
  if (trustMetrics[metric] > 0) {
 
4040
  return;
4041
  }
4042
 
4043
+ const trustScore = updateTrustBar();
 
4044
 
4045
  console.log(`Indice calculé pour sauvegarde: ${trustScore}%`);
4046
 
 
4047
  const data = {
4048
  timestamp: new Date().toISOString(),
4049
  scenario_id: scenarios[currentScenarioIndex].id,
 
4065
 
4066
  console.log("Données à envoyer:", JSON.stringify(data, null, 2));
4067
 
 
4068
  if (msgDiv) {
4069
  msgDiv.innerHTML = `
4070
  <div style="display: flex; align-items: center; gap: 10px;">
 
4076
  msgDiv.style.color = "#1976D2";
4077
  }
4078
 
 
4079
  fetch(GOOGLE_SCRIPT_URL, {
4080
  method: 'POST',
4081
+ mode: 'no-cors',
4082
  headers: {
4083
  'Content-Type': 'application/x-www-form-urlencoded',
4084
  },
4085
  body: new URLSearchParams(data)
4086
  })
4087
  .then(() => {
 
 
4088
  console.log("✅ Données envoyées avec succès");
4089
 
4090
  if (msgDiv) {
 
4104
  msgDiv.style.padding = "15px";
4105
  }
4106
 
 
4107
  setTimeout(() => {
4108
  if (msgDiv) {
4109
  msgDiv.innerHTML = "";
 
4137
  console.log("✅ Bouton de sauvegarde initialisé avec Google Sheets");
4138
  }
4139
 
 
4140
  function resetTrustEvaluation() {
4141
  console.log("Réinitialisation de l'évaluation...");
4142
 
 
4143
  for (const key in trustMetrics) {
4144
  trustMetrics[key] = 0;
4145
  }
4146
 
 
4147
  document.querySelectorAll(".stars").forEach(div => {
4148
  Array.from(div.children).forEach(star => {
4149
  star.classList.add("inactive");
 
4151
  });
4152
  });
4153
 
 
4154
  updateTrustBar();
4155
 
 
4156
  const commentField = document.getElementById("trustComment");
4157
  if (commentField) {
4158
  commentField.value = "";
 
4163
 
4164
  // ================= FONCTIONS UTILITAIRES =================
4165
 
 
4166
  function updateStats(scenario) {
4167
  if (!scenario) return;
4168
 
 
4174
  currentScenarioNum.textContent = scenario.id || "-";
4175
  }
4176
 
 
4177
  if (riskLevelElem) {
4178
  const risk = scenario.risk || 50;
4179
  let riskLevel = "Moyen";
 
4191
  riskLevelElem.style.color = riskColor;
4192
  }
4193
 
 
4194
  if (avgActivityElem && scenario.radar && scenario.radar.length > 0) {
 
4195
  const filteredRadar = scenario.radar.filter(metric => metric.label !== "Engagement global");
4196
  const avgRadar = filteredRadar.reduce((sum, item) => sum + item.value, 0) / filteredRadar.length;
4197
  avgActivityElem.textContent = Math.round(avgRadar) + "%";
4198
  }
4199
  }
4200
 
 
4201
  function fillSampleEvaluator() {
 
4202
  document.getElementById('gdprAccept').checked = true;
4203
  document.getElementById('gdprDecline').checked = false;
4204
 
 
4205
  initGDPR();
4206
 
 
4207
  document.getElementById("evaluatorName").value = "Martin Sophie";
4208
  document.getElementById("evaluatorEmail").value = "sophie.martin@exemple.fr";
4209
  document.getElementById("evaluatorRole").value = "enseignant";
 
4213
  showNotification("Exemple", "Champs d'évaluateur remplis avec un exemple", "info");
4214
  }
4215
 
 
4216
  function clearEvaluatorFields() {
 
4217
  document.getElementById('gdprDecline').checked = true;
4218
  document.getElementById('gdprAccept').checked = false;
4219
 
 
4220
  initGDPR();
4221
 
4222
  showNotification("Champs effacés", "Les informations d'évaluateur ont été effacées", "info");
4223
  }
4224
 
 
4225
  function showNotification(title, message, type = "info") {
4226
  console.log(`[${type}] ${title}: ${message}`);
4227
 
 
4233
  msgDiv.style.color = type === "success" ? "#2E7D32" :
4234
  type === "error" ? "#C62828" : "#1565C0";
4235
 
 
4236
  setTimeout(() => {
4237
  msgDiv.textContent = "";
4238
  msgDiv.style.background = "";
 
4241
  }
4242
  }
4243
 
 
4244
  function changePersistenceAnalysis() {
4245
  const modeSelect = document.getElementById("persistenceMode");
4246
  if (!modeSelect) return;
 
4250
 
4251
  if (!currentScenario) return;
4252
 
 
4253
  drawCompactEnrichedHeatmapWithAxes(currentScenario);
4254
 
4255
+ updatePersistenceIndicators(mode);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4256
  }
4257
 
4258
  // Exposer les fonctions globales