| <!DOCTYPE html>
|
| <html lang="fr">
|
| <head>
|
| <meta charset="UTF-8">
|
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| <title>Dashboard Réflexif – ReflAgent</title>
|
|
|
| <style>
|
|
|
| body {
|
| font-family: 'Segoe UI', Arial, sans-serif;
|
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
| margin: 0;
|
| padding: 20px;
|
| color: #333;
|
| min-height: 100vh;
|
| }
|
|
|
| h2, h3, h4 {
|
| color: #1976D2;
|
| margin-top: 0;
|
| }
|
|
|
| h2 {
|
| background: linear-gradient(90deg, #1976D2, #2196F3);
|
| -webkit-background-clip: text;
|
| -webkit-text-fill-color: transparent;
|
| padding: 10px 0;
|
| border-bottom: 2px solid #e3f2fd;
|
| margin-bottom: 25px;
|
| }
|
|
|
| h3 {
|
| background: #e3f2fd;
|
| padding: 12px 15px;
|
| border-radius: 8px;
|
| margin: 25px 0 15px;
|
| display: flex;
|
| align-items: center;
|
| gap: 10px;
|
| }
|
|
|
| h3::before {
|
| content: '';
|
| display: inline-block;
|
| width: 6px;
|
| height: 24px;
|
| background: #1976D2;
|
| border-radius: 3px;
|
| }
|
|
|
| #reflection {
|
| background: white;
|
| padding: 30px;
|
| border-radius: 20px;
|
| max-width: 1400px;
|
| margin: auto;
|
| box-shadow: 0 10px 40px rgba(0,0,0,0.08);
|
| border: 1px solid #e0e0e0;
|
| }
|
|
|
|
|
| .tabs-container {
|
| margin-bottom: 30px;
|
| }
|
|
|
| .tabs {
|
| display: flex;
|
| background: #f8f9fa;
|
| border-radius: 12px;
|
| padding: 5px;
|
| margin-bottom: 20px;
|
| border: 1px solid #e0e0e0;
|
| flex-wrap: wrap;
|
| }
|
|
|
| .tab-btn {
|
| flex: 1;
|
| padding: 15px 20px;
|
| border: none;
|
| background: transparent;
|
| color: #666;
|
| font-weight: 600;
|
| font-size: 16px;
|
| cursor: pointer;
|
| border-radius: 8px;
|
| transition: all 0.3s ease;
|
| display: flex;
|
| align-items: center;
|
| justify-content: center;
|
| gap: 10px;
|
| min-width: 200px;
|
| }
|
|
|
| .tab-btn:hover {
|
| background: rgba(25, 118, 210, 0.1);
|
| color: #1976D2;
|
| }
|
|
|
| .tab-btn.active {
|
| background: #1976D2;
|
| color: white;
|
| box-shadow: 0 3px 8px rgba(25, 118, 210, 0.2);
|
| }
|
|
|
| .tab-content {
|
| display: none;
|
| animation: fadeIn 0.5s ease;
|
| }
|
|
|
| .tab-content.active {
|
| display: block;
|
| }
|
|
|
|
|
| #tab-welcome {
|
| padding: 20px;
|
| }
|
|
|
| .welcome-header {
|
| text-align: center;
|
| margin-bottom: 40px;
|
| padding-bottom: 30px;
|
| border-bottom: 2px solid #e3f2fd;
|
| }
|
|
|
| .welcome-title {
|
| font-size: 2.2em;
|
| color: #1976D2;
|
| margin-bottom: 15px;
|
| display: flex;
|
| align-items: center;
|
| justify-content: center;
|
| gap: 15px;
|
| }
|
|
|
| .welcome-subtitle {
|
| font-size: 1.2em;
|
| color: #666;
|
| max-width: 800px;
|
| margin: 0 auto 25px;
|
| line-height: 1.6;
|
| }
|
|
|
| .welcome-card {
|
| background: linear-gradient(135deg, #E3F2FD, #BBDEFB);
|
| border-radius: 15px;
|
| padding: 30px;
|
| margin-bottom: 30px;
|
| border-left: 6px solid #1976D2;
|
| box-shadow: 0 5px 15px rgba(0,0,0,0.05);
|
| }
|
|
|
| .welcome-card h4 {
|
| color: #1976D2;
|
| margin-top: 0;
|
| margin-bottom: 20px;
|
| display: flex;
|
| align-items: center;
|
| gap: 10px;
|
| font-size: 1.4em;
|
| }
|
|
|
| .welcome-card p {
|
| line-height: 1.7;
|
| color: #333;
|
| margin-bottom: 15px;
|
| }
|
|
|
| .welcome-card ul {
|
| padding-left: 20px;
|
| margin: 15px 0;
|
| }
|
|
|
| .welcome-card li {
|
| margin-bottom: 10px;
|
| line-height: 1.6;
|
| color: #444;
|
| }
|
|
|
| .welcome-features {
|
| display: grid;
|
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
| gap: 20px;
|
| margin: 30px 0;
|
| }
|
|
|
| .feature-item {
|
| background: white;
|
| border-radius: 12px;
|
| padding: 25px;
|
| box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
| border-top: 4px solid #1976D2;
|
| transition: transform 0.3s;
|
| }
|
|
|
| .feature-item:hover {
|
| transform: translateY(-5px);
|
| box-shadow: 0 8px 20px rgba(0,0,0,0.12);
|
| }
|
|
|
| .feature-icon {
|
| font-size: 32px;
|
| margin-bottom: 15px;
|
| color: #1976D2;
|
| }
|
|
|
| .feature-title {
|
| font-size: 1.2em;
|
| font-weight: 600;
|
| color: #1976D2;
|
| margin-bottom: 12px;
|
| }
|
|
|
| .feature-description {
|
| color: #555;
|
| line-height: 1.6;
|
| font-size: 0.95em;
|
| }
|
|
|
| .how-to-start {
|
| background: linear-gradient(135deg, #E8F5E9, #C8E6C9);
|
| border-radius: 15px;
|
| padding: 30px;
|
| margin-top: 40px;
|
| border-left: 6px solid #43A047;
|
| }
|
|
|
| .how-to-start h4 {
|
| color: #2E7D32;
|
| }
|
|
|
| .step-list {
|
| counter-reset: step-counter;
|
| margin: 20px 0;
|
| }
|
|
|
| .step-item {
|
| counter-increment: step-counter;
|
| margin-bottom: 20px;
|
| padding-left: 50px;
|
| position: relative;
|
| }
|
|
|
| .step-item::before {
|
| content: counter(step-counter);
|
| position: absolute;
|
| left: 0;
|
| top: 0;
|
| background: #1976D2;
|
| color: white;
|
| width: 32px;
|
| height: 32px;
|
| border-radius: 50%;
|
| display: flex;
|
| align-items: center;
|
| justify-content: center;
|
| font-weight: bold;
|
| }
|
|
|
| .step-item strong {
|
| color: #1976D2;
|
| display: block;
|
| margin-bottom: 5px;
|
| }
|
|
|
|
|
| .nav {
|
| display: flex;
|
| justify-content: space-between;
|
| align-items: center;
|
| margin-bottom: 30px;
|
| background: linear-gradient(90deg, #e3f2fd, #f3e5f5);
|
| padding: 15px 25px;
|
| border-radius: 12px;
|
| border: 1px solid #bbdefb;
|
| flex-wrap: wrap;
|
| }
|
|
|
| #scenarioTitle {
|
| font-size: 1.4em;
|
| color: #333;
|
| text-align: center;
|
| flex-grow: 1;
|
| margin: 0 20px;
|
| word-break: break-word;
|
| }
|
|
|
| button {
|
| background: linear-gradient(135deg, #1976D2, #2196F3);
|
| color: white;
|
| border: none;
|
| padding: 12px 25px;
|
| border-radius: 10px;
|
| cursor: pointer;
|
| font-weight: 600;
|
| font-size: 15px;
|
| transition: all 0.3s ease;
|
| box-shadow: 0 3px 8px rgba(25, 118, 210, 0.2);
|
| display: flex;
|
| align-items: center;
|
| gap: 8px;
|
| white-space: nowrap;
|
| }
|
|
|
| button:hover:not(:disabled) {
|
| transform: translateY(-2px);
|
| box-shadow: 0 5px 15px rgba(25, 118, 210, 0.3);
|
| }
|
|
|
| button:active:not(:disabled) {
|
| transform: translateY(0);
|
| }
|
|
|
| button:disabled {
|
| opacity: 0.5;
|
| cursor: not-allowed;
|
| background: #b0bec5;
|
| }
|
|
|
|
|
| #tab-evaluator .evaluator-info {
|
| background: linear-gradient(135deg, #fff3e0, #ffe0b2);
|
| padding: 25px;
|
| border-radius: 15px;
|
| border-left: 6px solid #ff9800;
|
| margin: 20px 0;
|
| }
|
|
|
| #tab-evaluator .evaluator-info h4 {
|
| color: #ff9800;
|
| margin-top: 0;
|
| margin-bottom: 20px;
|
| display: flex;
|
| align-items: center;
|
| gap: 10px;
|
| font-size: 20px;
|
| }
|
|
|
| .evaluator-field {
|
| margin-bottom: 20px;
|
| background: white;
|
| padding: 20px;
|
| border-radius: 10px;
|
| border: 1px solid #FFE0B2;
|
| }
|
|
|
| .evaluator-field label {
|
| display: block;
|
| margin-bottom: 12px;
|
| color: #333;
|
| font-weight: 600;
|
| font-size: 15px;
|
| }
|
|
|
| .evaluator-field input[type="text"],
|
| .evaluator-field select {
|
| width: 100%;
|
| padding: 14px 18px;
|
| border: 2px solid #e0e0e0;
|
| border-radius: 8px;
|
| font-size: 15px;
|
| transition: all 0.3s;
|
| box-sizing: border-box;
|
| background: white;
|
| }
|
|
|
| .evaluator-field input[type="text"]:focus,
|
| .evaluator-field select:focus {
|
| outline: none;
|
| border-color: #1976D2;
|
| box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);
|
| }
|
|
|
| .evaluator-field input:disabled,
|
| .evaluator-field select:disabled {
|
| background: #f5f5f5;
|
| color: #999;
|
| cursor: not-allowed;
|
| }
|
|
|
| .evaluator-field small {
|
| display: block;
|
| margin-top: 8px;
|
| color: #666;
|
| font-size: 13px;
|
| font-style: italic;
|
| }
|
|
|
|
|
| .gdpr-options {
|
| display: flex;
|
| gap: 30px;
|
| margin-top: 10px;
|
| flex-wrap: wrap;
|
| }
|
|
|
| .gdpr-option {
|
| display: flex;
|
| align-items: center;
|
| gap: 10px;
|
| cursor: pointer;
|
| padding: 12px 20px;
|
| border-radius: 8px;
|
| background: white;
|
| border: 2px solid #e0e0e0;
|
| transition: all 0.3s;
|
| flex: 1;
|
| min-width: 250px;
|
| }
|
|
|
| .gdpr-option:hover {
|
| border-color: #1976D2;
|
| background: #f0f7ff;
|
| }
|
|
|
| .gdpr-option input[type="radio"] {
|
| width: 20px;
|
| height: 20px;
|
| cursor: pointer;
|
| }
|
|
|
| .gdpr-option span {
|
| font-size: 15px;
|
| font-weight: 500;
|
| color: #333;
|
| }
|
|
|
| #anonymousMessage {
|
| background: #E3F2FD;
|
| padding: 18px;
|
| border-radius: 10px;
|
| margin-top: 20px;
|
| border-left: 4px solid #1976D2;
|
| animation: fadeIn 0.5s ease;
|
| }
|
|
|
| #anonymousMessage p {
|
| margin: 0;
|
| color: #1976D2;
|
| font-size: 14px;
|
| line-height: 1.5;
|
| }
|
|
|
|
|
| #tab-dashboard .manifest-item {
|
| background: linear-gradient(135deg, #f9fbe7, #f0f4c3);
|
| padding: 15px;
|
| border-radius: 12px;
|
| border-left: 6px solid #cddc39;
|
| margin: 15px 0;
|
| box-shadow: 0 3px 10px rgba(0,0,0,0.05);
|
| font-size: 14px;
|
| }
|
|
|
| .manifest-item b {
|
| color: #689f38;
|
| }
|
|
|
|
|
| #competence-bars {
|
| background: white;
|
| padding: 20px;
|
| border-radius: 12px;
|
| border: 1px solid #e0e0e0;
|
| margin: 15px 0;
|
| }
|
|
|
| .compact-competences-grid {
|
| display: grid;
|
| grid-template-columns: repeat(4, 1fr);
|
| grid-template-rows: repeat(3, auto);
|
| gap: 10px;
|
| margin: 10px 0;
|
| }
|
|
|
| .compact-competence-matrix-item {
|
| padding: 1px;
|
| background: linear-gradient(135deg, #f8f9fa, #e9ecef);
|
| border-radius: 1.5px;
|
| border-left: 1px solid #1976D2;
|
| transition: all 0.3s ease;
|
| height: 100%;
|
| display: flex;
|
| flex-direction: column;
|
| justify-content: space-between;
|
| min-height: 30px;
|
| }
|
|
|
| .compact-competence-matrix-item:hover {
|
| transform: translateY(-1px);
|
| box-shadow: 0 1px 6px rgba(0,0,0,0.05);
|
| background: linear-gradient(135deg, #e3f2fd, #bbdefb);
|
| }
|
|
|
| .compact-matrix-competence-label {
|
| font-size: 12px;
|
| font-weight: 600;
|
| color: #333;
|
| margin-bottom: 5px;
|
| line-height: 1.2;
|
| flex-grow: 1;
|
| overflow: hidden;
|
| text-overflow: ellipsis;
|
| display: -webkit-box;
|
| -webkit-line-clamp: 2;
|
| -webkit-box-orient: vertical;
|
| max-height: 30px;
|
| }
|
|
|
| .compact-matrix-competence-value {
|
| font-size: 12px;
|
| font-weight: bold;
|
| color: #1976D2;
|
| text-align: center;
|
| margin: 3px 0;
|
| min-height: 15px;
|
| }
|
|
|
| .compact-matrix-competence-value.high { color: #43A047; }
|
| .compact-matrix-competence-value.medium { color: #FB8C00; }
|
| .compact-matrix-competence-value.low { color: #E53935; }
|
|
|
| .compact-matrix-competence-bar {
|
| height: 3px;
|
| background: #e0e0e0;
|
| border-radius: 1px;
|
| overflow: hidden;
|
| margin: 2px 0;
|
| }
|
|
|
| .compact-matrix-competence-fill {
|
| height: 100%;
|
| border-radius: 1px;
|
| transition: width 0.5s ease;
|
| }
|
|
|
|
|
| .compact-competence-matrix-item > div:last-child {
|
| font-size: 7px;
|
| margin-top: 1px;
|
| display: flex;
|
| justify-content: space-between;
|
| color: #999;
|
| }
|
|
|
|
|
| .compact-radar-legend {
|
| display: flex;
|
| justify-content: center;
|
| gap: 15px;
|
| margin: 15px 0;
|
| flex-wrap: wrap;
|
| padding: 10px;
|
| background: white;
|
| border-radius: 8px;
|
| border: 1px solid #e0e0e0;
|
| }
|
|
|
| .compact-legend-item {
|
| display: flex;
|
| align-items: center;
|
| gap: 8px;
|
| padding: 6px 10px;
|
| background: #f8f9fa;
|
| border-radius: 6px;
|
| font-size: 12px;
|
| }
|
|
|
| .compact-legend-color {
|
| width: 16px;
|
| height: 16px;
|
| border-radius: 4px;
|
| border: 2px solid white;
|
| }
|
|
|
| .compact-legend-low { background: linear-gradient(135deg, #e53935, #f44336); }
|
| .compact-legend-medium { background: linear-gradient(135deg, #fb8c00, #ff9800); }
|
| .compact-legend-high { background: linear-gradient(135deg, #43a047, #4caf50); }
|
|
|
|
|
| .compact-radar-metrics-grid {
|
| display: grid;
|
| grid-template-columns: repeat(8, 1fr);
|
| gap: 8px;
|
| margin: 15px 0;
|
| }
|
|
|
| .compact-metric-card {
|
| background: white;
|
| border-radius: 8px;
|
| padding: 10px;
|
| box-shadow: 0 2px 5px rgba(0,0,0,0.06);
|
| border-left: 3px solid #1976D2;
|
| transition: transform 0.2s;
|
| text-align: center;
|
| min-height: 90px;
|
| display: flex;
|
| flex-direction: column;
|
| justify-content: space-between;
|
| }
|
|
|
| .compact-metric-card:hover {
|
| transform: translateY(-2px);
|
| box-shadow: 0 3px 8px rgba(0,0,0,0.1);
|
| }
|
|
|
| .compact-metric-icon {
|
| font-size: 18px;
|
| margin-bottom: 5px;
|
| }
|
|
|
| .compact-metric-name {
|
| font-weight: 600;
|
| color: #333;
|
| margin-bottom: 3px;
|
| font-size: 11px;
|
| line-height: 1.2;
|
| height: 26px;
|
| overflow: hidden;
|
| display: -webkit-box;
|
| -webkit-line-clamp: 2;
|
| -webkit-box-orient: vertical;
|
| }
|
|
|
| .compact-metric-value {
|
| font-size: 16px;
|
| font-weight: bold;
|
| color: #1976D2;
|
| margin: 5px 0;
|
| }
|
|
|
| .compact-metric-value.high { color: #43A047; }
|
| .compact-metric-value.medium { color: #FB8C00; }
|
| .compact-metric-value.low { color: #E53935; }
|
|
|
| .compact-metric-description {
|
| font-size: 10px;
|
| color: #666;
|
| margin-top: 3px;
|
| line-height: 1.2;
|
| height: 24px;
|
| overflow: hidden;
|
| display: -webkit-box;
|
| -webkit-line-clamp: 2;
|
| -webkit-box-orient: vertical;
|
| }
|
|
|
|
|
| #radar-container {
|
| background: white;
|
| padding: 15px;
|
| border-radius: 12px;
|
| border: 1px solid #e0e0e0;
|
| margin: 15px 0;
|
| }
|
|
|
| #radar {
|
| max-width: 100%;
|
| height: auto;
|
| }
|
|
|
|
|
| .compact-radar-bot-message {
|
| background: linear-gradient(135deg, #E3F2FD, #BBDEFB);
|
| padding: 15px;
|
| border-radius: 10px;
|
| border-left: 4px solid #1976D2;
|
| margin: 15px 0;
|
| }
|
|
|
| .compact-radar-bot-header {
|
| display: flex;
|
| align-items: center;
|
| gap: 10px;
|
| margin-bottom: 10px;
|
| }
|
|
|
| .compact-radar-bot-icon {
|
| font-size: 20px;
|
| background: #1976D2;
|
| color: white;
|
| width: 40px;
|
| height: 40px;
|
| border-radius: 50%;
|
| display: flex;
|
| align-items: center;
|
| justify-content: center;
|
| }
|
|
|
| .compact-radar-bot-title {
|
| font-size: 16px;
|
| font-weight: 600;
|
| color: #1976D2;
|
| margin: 0;
|
| }
|
|
|
| .compact-radar-bot-content {
|
| font-size: 14px;
|
| line-height: 1.5;
|
| color: #333;
|
| margin: 0;
|
| }
|
|
|
| .compact-radar-bot-insights {
|
| background: white;
|
| padding: 10px;
|
| border-radius: 8px;
|
| margin-top: 10px;
|
| border: 1px solid #E3F2FD;
|
| }
|
|
|
| .compact-radar-insight-item {
|
| display: flex;
|
| align-items: center;
|
| gap: 8px;
|
| margin-bottom: 6px;
|
| padding: 6px 10px;
|
| border-radius: 6px;
|
| background: #F5F5F5;
|
| font-size: 12px;
|
| }
|
|
|
|
|
| .compact-heatmap-and-indicators {
|
| background: white;
|
| padding: 15px;
|
| border-radius: 12px;
|
| border: 1px solid #e0e0e0;
|
| margin: 15px 0;
|
| }
|
|
|
| .compact-heatmap-container {
|
| display: flex;
|
| gap: 20px;
|
| flex-wrap: wrap;
|
| margin-bottom: 15px;
|
| }
|
|
|
| .compact-heatmap-left {
|
| flex: 1;
|
| min-width: 300px;
|
| }
|
|
|
| .compact-heatmap-right {
|
| flex: 1;
|
| min-width: 300px;
|
| }
|
|
|
| .compact-heatmap-analysis {
|
| margin-bottom: 15px;
|
| }
|
|
|
| .compact-analysis-controls {
|
| display: flex;
|
| align-items: center;
|
| gap: 10px;
|
| margin-bottom: 15px;
|
| padding: 10px;
|
| background: #f8f9fa;
|
| border-radius: 8px;
|
| }
|
|
|
| .compact-analysis-controls label {
|
| font-weight: 600;
|
| color: #1976D2;
|
| font-size: 14px;
|
| }
|
|
|
| .compact-analysis-controls select {
|
| padding: 8px 12px;
|
| border-radius: 6px;
|
| border: 2px solid #1976D2;
|
| background: white;
|
| color: #333;
|
| font-weight: 500;
|
| cursor: pointer;
|
| flex-grow: 1;
|
| font-size: 14px;
|
| }
|
|
|
| #heatmap {
|
| max-width: 100%;
|
| height: auto;
|
| border-radius: 8px;
|
| }
|
|
|
|
|
| .compact-enriched-legend {
|
| background: white;
|
| padding: 15px;
|
| border-radius: 10px;
|
| border: 1px solid #e0e0e0;
|
| margin: 10px 0;
|
| height: auto;
|
| display: flex;
|
| align-items: flex-start;
|
| justify-content: space-between;
|
| }
|
|
|
| .compact-legend-section h5 {
|
| color: #1976D2;
|
| margin: 0 0 10px 0;
|
| font-size: 14px;
|
| display: flex;
|
| align-items: center;
|
| gap: 6px;
|
| }
|
|
|
| .compact-legend-section {
|
| margin: 0;
|
| padding: 0;
|
| display: flex;
|
| flex-direction: column;
|
| gap: 5px;
|
| width: 100%;
|
| }
|
|
|
| .compact-legend-grid {
|
| display: flex;
|
| gap: 10px;
|
| flex-wrap: wrap;
|
| }
|
|
|
| .compact-legend-item-small {
|
| display: flex;
|
| align-items: center;
|
| gap: 5px;
|
| font-size: 11px;
|
| white-space: nowrap;
|
| padding: 4px 8px;
|
| background: #f8f9fa;
|
| border-radius: 4px;
|
| }
|
|
|
| .compact-legend-color-small {
|
| width: 14px;
|
| height: 14px;
|
| border-radius: 3px;
|
| border: 1px solid white;
|
| box-shadow: 0 1px 2px rgba(0,0,0,0.1);
|
| }
|
|
|
|
|
| .compact-persistence-analysis {
|
| background: linear-gradient(135deg, #e3f2fd, #f3e5f5);
|
| padding: 15px;
|
| border-radius: 10px;
|
| border-left: 4px solid #1976D2;
|
| margin: 15px 0;
|
| }
|
|
|
| .compact-persistence-indicators {
|
| display: flex;
|
| flex-direction: column;
|
| gap: 8px;
|
| margin-bottom: 10px;
|
| }
|
|
|
| .compact-indicator {
|
| display: flex;
|
| align-items: center;
|
| gap: 8px;
|
| padding: 8px 10px;
|
| background: white;
|
| border-radius: 6px;
|
| font-size: 12px;
|
| border-left: 3px solid #1976D2;
|
| }
|
|
|
| .compact-indicator-dot {
|
| width: 10px;
|
| height: 10px;
|
| border-radius: 50%;
|
| }
|
|
|
| .compact-persistence-text {
|
| font-size: 12px;
|
| line-height: 1.4;
|
| }
|
|
|
| .compact-persistence-text > div {
|
| margin-bottom: 6px;
|
| padding: 8px;
|
| background: white;
|
| border-radius: 6px;
|
| border-left: 3px solid #1976D2;
|
| }
|
|
|
|
|
| .audio-narration-compact {
|
| background: #f8f9fa;
|
| border-radius: 8px;
|
| margin: 8px 0;
|
| display: flex;
|
| align-items: center;
|
| gap: 12px;
|
| padding: 8px 15px;
|
| border: 1px solid #e9ecef;
|
| }
|
|
|
| .audio-narration-compact .audio-icon {
|
| font-size: 18px;
|
| color: #1976D2;
|
| display: flex;
|
| align-items: center;
|
| gap: 6px;
|
| }
|
|
|
| .audio-narration-compact .audio-icon span {
|
| font-size: 12px;
|
| font-weight: 500;
|
| color: #495057;
|
| }
|
|
|
| .audio-narration-compact .audio-controls {
|
| display: flex;
|
| align-items: center;
|
| gap: 8px;
|
| flex-wrap: wrap;
|
| }
|
|
|
| .audio-narration-compact .audio-btn {
|
| background: #e9ecef;
|
| color: #495057;
|
| padding: 4px 10px;
|
| font-size: 11px;
|
| border-radius: 6px;
|
| box-shadow: none;
|
| font-weight: 500;
|
| }
|
|
|
| .audio-narration-compact .audio-btn:hover {
|
| background: #1976D2;
|
| color: white;
|
| transform: none;
|
| }
|
|
|
| .audio-narration-compact .audio-progress {
|
| width: 120px;
|
| height: 3px;
|
| background: #dee2e6;
|
| border-radius: 3px;
|
| overflow: hidden;
|
| cursor: pointer;
|
| }
|
|
|
| .audio-narration-compact .audio-progress-fill {
|
| height: 100%;
|
| background: #1976D2;
|
| width: 0%;
|
| transition: width 0.1s linear;
|
| }
|
|
|
| .audio-narration-compact .audio-time {
|
| font-size: 10px;
|
| font-family: monospace;
|
| color: #868e96;
|
| }
|
|
|
| .audio-narration-compact .audio-status {
|
| font-size: 10px;
|
| color: #6c757d;
|
| font-style: italic;
|
| }
|
|
|
|
|
| #tab-evaluation #reflagent {
|
| background: linear-gradient(135deg, #e8f5e9, #c8e6c9);
|
| padding: 25px;
|
| border-radius: 15px;
|
| border-left: 8px solid #43a047;
|
| margin: 25px 0;
|
| font-size: 16px;
|
| line-height: 1.6;
|
| position: relative;
|
| overflow: hidden;
|
| min-height: 100px;
|
| display: flex;
|
| align-items: center;
|
| }
|
|
|
| #tab-evaluation #reflagent::before {
|
| content: '🤖';
|
| position: absolute;
|
| top: 15px;
|
| right: 15px;
|
| font-size: 40px;
|
| opacity: 0.2;
|
| }
|
|
|
|
|
| #tab-evaluation hr {
|
| border: none;
|
| height: 2px;
|
| background: linear-gradient(90deg, #1976D2, transparent);
|
| margin: 40px 0;
|
| }
|
|
|
| .trust-item {
|
| margin-bottom: 20px;
|
| padding: 15px;
|
| background: #f8f9fa;
|
| border-radius: 12px;
|
| transition: transform 0.3s;
|
| }
|
|
|
| .trust-item:hover {
|
| transform: translateX(5px);
|
| background: #f1f3f4;
|
| }
|
|
|
| .trust-item b {
|
| display: block;
|
| margin-bottom: 10px;
|
| color: #1976D2;
|
| font-size: 15px;
|
| }
|
|
|
| .stars {
|
| display: flex;
|
| gap: 8px;
|
| margin: 10px 0;
|
| }
|
|
|
| .stars span {
|
| font-size: 32px;
|
| cursor: pointer;
|
| color: #e0e0e0;
|
| transition: all 0.2s;
|
| text-shadow: none;
|
| }
|
|
|
| .stars span.active {
|
| color: #ffd54f;
|
| text-shadow: 0 2px 4px rgba(255, 213, 79, 0.3);
|
| }
|
|
|
| .stars span:hover {
|
| transform: scale(1.2);
|
| }
|
|
|
| .stars span.inactive {
|
| color: #e0e0e0;
|
| text-shadow: none;
|
| }
|
|
|
| .stars span.inactive:hover {
|
| color: #ffd54f;
|
| }
|
|
|
|
|
| textarea {
|
| width: 100%;
|
| min-height: 120px;
|
| border-radius: 12px;
|
| padding: 15px;
|
| border: 2px solid #e0e0e0;
|
| font-family: inherit;
|
| font-size: 14px;
|
| resize: vertical;
|
| transition: all 0.3s;
|
| margin-bottom: 20px;
|
| }
|
|
|
| textarea:focus {
|
| outline: none;
|
| border-color: #1976D2;
|
| box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.1);
|
| }
|
|
|
|
|
| .progress-container {
|
| width: 100%;
|
| background: #f5f5f5;
|
| border-radius: 12px;
|
| height: 24px;
|
| margin: 8px 0 20px;
|
| overflow: hidden;
|
| box-shadow: inset 0 2px 5px rgba(0,0,0,0.1);
|
| }
|
|
|
| #trustBar {
|
| height: 100%;
|
| border-radius: 10px;
|
| color: white;
|
| font-size: 14px;
|
| text-align: center;
|
| line-height: 24px;
|
| font-weight: bold;
|
| transition: width 0.5s ease, background 0.5s ease;
|
| position: relative;
|
| overflow: hidden;
|
| width: 0%;
|
| background: #e0e0e0;
|
| display: flex;
|
| align-items: center;
|
| justify-content: center;
|
| padding: 0 10px;
|
| box-sizing: border-box;
|
| }
|
|
|
| #trustBar::after {
|
| content: '';
|
| position: absolute;
|
| top: 0;
|
| left: 0;
|
| right: 0;
|
| bottom: 0;
|
| background: linear-gradient(90deg,
|
| transparent,
|
| rgba(255,255,255,0.4),
|
| transparent
|
| );
|
| animation: shimmer 2s infinite;
|
| }
|
|
|
|
|
| #crossReadersBtn {
|
| background: linear-gradient(135deg, #43A047, #4CAF50) !important;
|
| color: white;
|
| border: none;
|
| padding: 12px 25px;
|
| border-radius: 10px;
|
| cursor: pointer;
|
| font-weight: 600;
|
| font-size: 15px;
|
| transition: all 0.3s ease;
|
| box-shadow: 0 3px 8px rgba(67, 160, 71, 0.2);
|
| display: flex;
|
| align-items: center;
|
| justify-content: center;
|
| gap: 8px;
|
| width: 100%;
|
| }
|
|
|
| #crossReadersBtn:hover:not(:disabled) {
|
| transform: translateY(-2px);
|
| box-shadow: 0 5px 15px rgba(67, 160, 71, 0.3);
|
| background: linear-gradient(135deg, #388E3C, #43A047) !important;
|
| }
|
|
|
| #crossReadersBtn:active:not(:disabled) {
|
| transform: translateY(0);
|
| }
|
|
|
| #crossReadersBtn:disabled {
|
| opacity: 0.5;
|
| cursor: not-allowed;
|
| background: #b0bec5 !important;
|
| }
|
|
|
|
|
| #saveTrustMsg {
|
| padding: 10px 15px;
|
| border-radius: 8px;
|
| margin: 10px 0;
|
| font-weight: 500;
|
| text-align: center;
|
| transition: all 0.3s;
|
| min-height: 50px;
|
| display: flex;
|
| align-items: center;
|
| justify-content: center;
|
| }
|
|
|
|
|
| .stats-grid {
|
| display: grid;
|
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
| gap: 15px;
|
| margin: 20px 0;
|
| }
|
|
|
| .stat-item {
|
| background: linear-gradient(135deg, #e3f2fd, #f3e5f5);
|
| padding: 15px;
|
| border-radius: 10px;
|
| text-align: center;
|
| transition: transform 0.3s;
|
| }
|
|
|
| .stat-item:hover {
|
| transform: translateY(-3px);
|
| box-shadow: 0 5px 15px rgba(0,0,0,0.1);
|
| }
|
|
|
| .stat-value {
|
| font-size: 28px;
|
| font-weight: bold;
|
| color: #1976D2;
|
| margin: 10px 0;
|
| }
|
|
|
| .stat-label {
|
| font-size: 13px;
|
| color: #666;
|
| font-weight: 500;
|
| }
|
|
|
|
|
| #tab-example {
|
| padding: 20px;
|
| }
|
|
|
| .example-container {
|
| background: linear-gradient(135deg, #f3e5f5, #e1bee7);
|
| padding: 25px;
|
| border-radius: 15px;
|
| border-left: 6px solid #7b1fa2;
|
| margin-bottom: 30px;
|
| }
|
|
|
| .example-container h4 {
|
| color: #7b1fa2;
|
| margin-top: 0;
|
| display: flex;
|
| align-items: center;
|
| gap: 10px;
|
| }
|
|
|
| .example-analysis-box {
|
| background: white;
|
| padding: 20px;
|
| border-radius: 10px;
|
| border-left: 4px solid #7b1fa2;
|
| margin: 15px 0;
|
| box-shadow: 0 3px 10px rgba(0,0,0,0.05);
|
| }
|
|
|
| .example-message {
|
| background: linear-gradient(135deg, #e8f5e9, #c8e6c9);
|
| padding: 20px;
|
| border-radius: 10px;
|
| border-left: 6px solid #43a047;
|
| margin: 20px 0;
|
| line-height: 1.6;
|
| font-size: 15px;
|
| }
|
|
|
| .example-message::before {
|
| content: '🤖';
|
| float: left;
|
| margin-right: 10px;
|
| font-size: 24px;
|
| }
|
|
|
| .example-competences {
|
| background: #f9fbe7;
|
| padding: 15px;
|
| border-radius: 10px;
|
| margin: 15px 0;
|
| }
|
|
|
| .example-competences ul {
|
| margin: 10px 0;
|
| padding-left: 20px;
|
| }
|
|
|
| .example-competences li {
|
| margin-bottom: 8px;
|
| line-height: 1.4;
|
| }
|
|
|
| .example-metrics-table {
|
| width: 100%;
|
| border-collapse: collapse;
|
| margin: 20px 0;
|
| background: white;
|
| border-radius: 10px;
|
| overflow: hidden;
|
| box-shadow: 0 3px 10px rgba(0,0,0,0.05);
|
| }
|
|
|
| .example-metrics-table th {
|
| background: linear-gradient(135deg, #7b1fa2, #9c27b0);
|
| color: white;
|
| padding: 15px;
|
| text-align: left;
|
| font-weight: 600;
|
| }
|
|
|
| .example-metrics-table td {
|
| padding: 15px;
|
| border-bottom: 1px solid #eee;
|
| }
|
|
|
| .example-metrics-table tr:last-child td {
|
| border-bottom: none;
|
| }
|
|
|
| .example-metrics-table tr:hover {
|
| background: #f5f5f5;
|
| }
|
|
|
| .metric-stars {
|
| color: #ffd54f;
|
| font-size: 18px;
|
| }
|
|
|
| .metric-observation {
|
| font-size: 13px;
|
| line-height: 1.4;
|
| }
|
|
|
| .metric-observation .success {
|
| color: #43a047;
|
| font-weight: 600;
|
| }
|
|
|
| .metric-observation .warning {
|
| color: #fb8c00;
|
| font-weight: 600;
|
| }
|
|
|
| .metric-observation .error {
|
| color: #e53935;
|
| font-weight: 600;
|
| }
|
|
|
| .example-summary {
|
| background: #e3f2fd;
|
| padding: 20px;
|
| border-radius: 10px;
|
| margin: 20px 0;
|
| }
|
|
|
| .example-summary ul {
|
| margin: 10px 0;
|
| padding-left: 20px;
|
| }
|
|
|
| .example-summary li {
|
| margin-bottom: 8px;
|
| line-height: 1.4;
|
| padding-left: 5px;
|
| }
|
|
|
| .example-separator {
|
| height: 1px;
|
| background: linear-gradient(90deg, #7b1fa2, transparent);
|
| margin: 25px 0;
|
| border: none;
|
| }
|
|
|
|
|
| @keyframes fadeIn {
|
| from { opacity: 0; transform: translateY(20px); }
|
| to { opacity: 1; transform: translateY(0); }
|
| }
|
|
|
| @keyframes slideIn {
|
| from { transform: translateX(100%); opacity: 0; }
|
| to { transform: translateX(0); opacity: 1; }
|
| }
|
|
|
| @keyframes slideOut {
|
| from { transform: translateX(0); opacity: 1; }
|
| to { transform: translateX(100%); opacity: 0; }
|
| }
|
|
|
| @keyframes pulse {
|
| 0% { transform: scale(1); }
|
| 50% { transform: scale(1.05); }
|
| 100% { transform: scale(1); }
|
| }
|
|
|
| @keyframes spin {
|
| 0% { transform: rotate(0deg); }
|
| 100% { transform: rotate(360deg); }
|
| }
|
|
|
| @keyframes shimmer {
|
| 0% { transform: translateX(-100%); }
|
| 100% { transform: translateX(100%); }
|
| }
|
|
|
|
|
| .tooltip {
|
| position: absolute;
|
| background: rgba(25, 118, 210, 0.95);
|
| color: white;
|
| padding: 12px 18px;
|
| border-radius: 10px;
|
| font-size: 14px;
|
| pointer-events: none;
|
| opacity: 0;
|
| transition: opacity 0.3s;
|
| z-index: 1000;
|
| max-width: 300px;
|
| box-shadow: 0 6px 20px rgba(0,0,0,0.2);
|
| border: 2px solid white;
|
| backdrop-filter: blur(5px);
|
| }
|
|
|
| .tooltip::after {
|
| content: '';
|
| position: absolute;
|
| top: 100%;
|
| left: 50%;
|
| margin-left: -10px;
|
| border-width: 10px;
|
| border-style: solid;
|
| border-color: rgba(25, 118, 210, 0.95) transparent transparent transparent;
|
| }
|
|
|
|
|
| ::-webkit-scrollbar {
|
| width: 10px;
|
| }
|
|
|
| ::-webkit-scrollbar-track {
|
| background: #f1f1f1;
|
| border-radius: 5px;
|
| }
|
|
|
| ::-webkit-scrollbar-thumb {
|
| background: linear-gradient(135deg, #1976D2, #2196F3);
|
| border-radius: 5px;
|
| }
|
|
|
| ::-webkit-scrollbar-thumb:hover {
|
| background: linear-gradient(135deg, #1565c0, #1976D2);
|
| }
|
|
|
|
|
| .loading {
|
| display: inline-block;
|
| width: 20px;
|
| height: 20px;
|
| border: 3px solid #f3f3f3;
|
| border-top: 3px solid #1976D2;
|
| border-radius: 50%;
|
| animation: spin 1s linear infinite;
|
| }
|
|
|
|
|
| .notification {
|
| position: fixed;
|
| top: 20px;
|
| right: 20px;
|
| background: white;
|
| padding: 18px;
|
| border-radius: 12px;
|
| box-shadow: 0 8px 25px rgba(0,0,0,0.15);
|
| border-left: 6px solid #1976D2;
|
| z-index: 10000;
|
| max-width: 320px;
|
| animation: slideIn 0.4s ease-out;
|
| display: flex;
|
| align-items: flex-start;
|
| gap: 12px;
|
| }
|
|
|
| .notification-icon {
|
| font-size: 28px;
|
| flex-shrink: 0;
|
| }
|
|
|
| .notification-content {
|
| flex-grow: 1;
|
| }
|
|
|
| .notification-title {
|
| font-weight: bold;
|
| color: #1976D2;
|
| margin-bottom: 5px;
|
| font-size: 15px;
|
| }
|
|
|
| .notification-message {
|
| color: #555;
|
| font-size: 13px;
|
| line-height: 1.4;
|
| }
|
|
|
| .notification-close {
|
| background: none;
|
| border: none;
|
| color: #999;
|
| cursor: pointer;
|
| padding: 0;
|
| font-size: 20px;
|
| line-height: 1;
|
| }
|
|
|
|
|
| @media (max-width: 1200px) {
|
| #reflection {
|
| padding: 20px;
|
| }
|
|
|
| .tabs {
|
| flex-direction: column;
|
| }
|
|
|
| .tab-btn {
|
| width: 100%;
|
| }
|
|
|
| .compact-competences-grid {
|
| grid-template-columns: repeat(3, 1fr);
|
| grid-template-rows: repeat(5, auto);
|
| }
|
|
|
| .compact-radar-metrics-grid {
|
| grid-template-columns: repeat(4, 1fr);
|
| grid-template-rows: repeat(2, auto);
|
| }
|
|
|
| .compact-heatmap-container {
|
| flex-direction: column;
|
| }
|
|
|
| .compact-enriched-legend {
|
| height: auto;
|
| flex-direction: column;
|
| gap: 10px;
|
| padding: 12px;
|
| }
|
|
|
| .welcome-features {
|
| grid-template-columns: repeat(2, 1fr);
|
| }
|
| }
|
|
|
| @media (max-width: 768px) {
|
| body {
|
| padding: 10px;
|
| }
|
|
|
| .nav {
|
| flex-direction: column;
|
| gap: 15px;
|
| text-align: center;
|
| }
|
|
|
| #scenarioTitle {
|
| margin: 10px 0;
|
| font-size: 1.2em;
|
| }
|
|
|
| button {
|
| width: 100%;
|
| justify-content: center;
|
| }
|
|
|
| .gdpr-options {
|
| flex-direction: column;
|
| gap: 10px;
|
| }
|
|
|
| .gdpr-option {
|
| min-width: 100%;
|
| }
|
|
|
| .compact-competences-grid {
|
| grid-template-columns: repeat(2, 1fr);
|
| grid-template-rows: repeat(7, auto);
|
| gap: 6px;
|
| }
|
|
|
| .compact-competence-matrix-item {
|
| padding: 5px;
|
| min-height: 50px;
|
| }
|
|
|
| .compact-matrix-competence-label {
|
| font-size: 8px;
|
| -webkit-line-clamp: 2;
|
| max-height: 18px;
|
| }
|
|
|
| .compact-matrix-competence-value {
|
| font-size: 11px;
|
| min-height: 13px;
|
| }
|
|
|
| .compact-radar-metrics-grid {
|
| grid-template-columns: repeat(4, 1fr);
|
| grid-template-rows: repeat(2, auto);
|
| gap: 6px;
|
| }
|
|
|
| .compact-metric-card {
|
| min-height: 85px;
|
| padding: 8px;
|
| }
|
|
|
| .compact-metric-name {
|
| font-size: 10px;
|
| height: 24px;
|
| }
|
|
|
| .compact-metric-value {
|
| font-size: 14px;
|
| }
|
|
|
| .compact-metric-description {
|
| font-size: 9px;
|
| height: 22px;
|
| }
|
|
|
| .compact-radar-legend {
|
| flex-direction: column;
|
| align-items: center;
|
| gap: 8px;
|
| }
|
|
|
| .compact-enriched-legend {
|
| height: auto;
|
| flex-direction: column;
|
| gap: 8px;
|
| padding: 10px;
|
| }
|
|
|
| .compact-legend-grid {
|
| flex-wrap: wrap;
|
| justify-content: center;
|
| }
|
|
|
| .compact-legend-item-small {
|
| font-size: 8px;
|
| }
|
|
|
| .compact-legend-color-small {
|
| width: 10px;
|
| height: 10px;
|
| }
|
|
|
| .compact-analysis-controls {
|
| flex-direction: column;
|
| align-items: stretch;
|
| }
|
|
|
| .compact-persistence-indicators {
|
| flex-direction: column;
|
| }
|
|
|
| .stats-grid {
|
| grid-template-columns: repeat(2, 1fr);
|
| }
|
|
|
| .tab-btn {
|
| min-width: 100%;
|
| }
|
|
|
| .example-metrics-table {
|
| display: block;
|
| overflow-x: auto;
|
| }
|
|
|
| .compact-heatmap-container {
|
| flex-direction: column;
|
| }
|
|
|
| .welcome-features {
|
| grid-template-columns: 1fr;
|
| }
|
|
|
| .welcome-title {
|
| font-size: 1.8em;
|
| flex-direction: column;
|
| gap: 10px;
|
| }
|
|
|
| .feature-item {
|
| padding: 20px;
|
| }
|
| }
|
|
|
| @media (max-width: 480px) {
|
| .stats-grid {
|
| grid-template-columns: 1fr;
|
| }
|
|
|
| .compact-radar-metrics-grid {
|
| grid-template-columns: repeat(2, 1fr);
|
| grid-template-rows: repeat(4, auto);
|
| gap: 5px;
|
| }
|
|
|
| .compact-metric-card {
|
| min-height: 80px;
|
| padding: 6px;
|
| }
|
|
|
| .compact-metric-name {
|
| font-size: 9px;
|
| height: 22px;
|
| }
|
|
|
| .compact-metric-value {
|
| font-size: 13px;
|
| }
|
|
|
| .compact-metric-description {
|
| font-size: 8px;
|
| height: 20px;
|
| }
|
|
|
| .compact-competences-grid {
|
| grid-template-columns: 1fr;
|
| grid-template-rows: repeat(14, auto);
|
| gap: 5px;
|
| }
|
|
|
| .compact-competence-matrix-item {
|
| min-height: 45px;
|
| }
|
|
|
| .compact-matrix-competence-label {
|
| font-size: 7px;
|
| -webkit-line-clamp: 2;
|
| max-height: 16px;
|
| }
|
|
|
| .example-metrics-table th,
|
| .example-metrics-table td {
|
| padding: 10px 8px;
|
| font-size: 13px;
|
| }
|
|
|
| .compact-heatmap-container {
|
| flex-direction: column;
|
| }
|
|
|
| .compact-enriched-legend {
|
| height: auto;
|
| padding: 8px;
|
| }
|
|
|
| .compact-legend-item-small {
|
| font-size: 7px;
|
| gap: 2px;
|
| }
|
|
|
| .audio-narration-compact {
|
| flex-wrap: wrap;
|
| justify-content: center;
|
| }
|
| }
|
| </style>
|
| </head>
|
|
|
| <body>
|
|
|
| <div id="reflection">
|
|
|
|
|
| <div class="nav">
|
| <button id="prevScenario">⬅️ Scénario précédent</button>
|
| <h3 id="scenarioTitle">Chargement...</h3>
|
| <button id="nextScenario">Scénario suivant ➡️</button>
|
| </div>
|
|
|
|
|
| <div class="tabs-container">
|
| <div class="tabs">
|
| <button class="tab-btn active" data-tab="tab-welcome">
|
| <span>🏠</span> Accueil
|
| </button>
|
| <button class="tab-btn" data-tab="tab-evaluator">
|
| <span>👤</span> Évaluateur (RGPD)
|
| </button>
|
| <button class="tab-btn" data-tab="tab-dashboard">
|
| <span>📊</span> Dashboard Étudiant
|
| </button>
|
| <button class="tab-btn" data-tab="tab-evaluation">
|
| <span>🤖</span> Message Réflexif & Évaluation
|
| </button>
|
| <button class="tab-btn" data-tab="tab-example">
|
| <span>📋</span> Exemple d'Analyse
|
| </button>
|
| </div>
|
|
|
|
|
| <div id="tab-welcome" class="tab-content active">
|
| <div class="welcome-header">
|
| <h1 class="welcome-title">🎓 Dashboard Réflexif – ReflAgent</h1>
|
| <p class="welcome-subtitle">
|
| Bienvenue sur notre outil d'évaluation qualitative des messages auto-réflexifs générés par l'IA et adaptés aux profils des apprenants. </p>
|
| </div>
|
|
|
| <div class="welcome-card">
|
| <h4><span>🎯</span> Objectif de l'outil</h4>
|
| <p>
|
| Cet outil permet d'<strong>évaluer la qualité des messages auto-réflexifs</strong> générés par <strong>ReflAgent</strong>,
|
| un tuteur pédagogique personnalisé basé sur l'IA, conçu pour favoriser l'apprentissage auto-régulé (SRL)
|
| en renforçant la conscience métacognitive par un accompagnement réflexif.
|
| Les messages réflexifs ciblent des dimensions clés, notamment la sensibilisation aux risques d'inactivité et d'échec, le degré d'activité et d'implication, ainsi que la stimulation de l'engagement et de la motivation.
|
| </p>
|
|
|
| <h4 style="margin-top: 25px;"><span>🤖</span> Qu'est-ce que ReflAgent ?</h4>
|
| <p>
|
| <strong>ReflAgent</strong> est un compagnon tutoriel IA sensible aux profils, conçu pour favoriser
|
| l'apprentissage auto-régulé (SRL) en améliorant la conscience métacognitive grâce à un soutien réflexif.
|
| Les messages auto-réflexifs sont personnalisés en fonction des profils des apprenants, tels que les étudiants en difficulté, inactifs, en progression ou à risque.
|
| </p>
|
|
|
| <p>
|
| Nous vous invitons à évaluer les messages réflexifs selon cinq métriques, en utilisant une échelle de Likert allant de 1 (très faible) à 5 (très élevée).
|
| </p>
|
| </div>
|
|
|
| <h3>📋 Présentation des volets de l'outil</h3>
|
|
|
| <div class="welcome-features">
|
| <div class="feature-item">
|
| <div class="feature-icon">👤</div>
|
| <div class="feature-title">Évaluateur (RGPD)</div>
|
| <div class="feature-description">
|
| <strong>Authentification et consentement RGPD</strong><br>
|
| Définissez votre profil d'évaluateur, votre niveau d'expertise et donnez votre consentement
|
| pour le traitement de vos données personnelles selon le règlement européen.
|
| </div>
|
| </div>
|
|
|
| <div class="feature-item">
|
| <div class="feature-icon">📊</div>
|
| <div class="feature-title">Dashboard Étudiant</div>
|
| <div class="feature-description">
|
| <strong>Visualisation complète du profil d'apprentissage</strong><br>
|
| Explorez le manifeste de l'étudiant, ses compétences et son engagement à l'aide d'un radar, ainsi que sa persistance et la gestion de l'effort via une heatmap temporelle intégrant des indicateurs de persévérance.
|
| </div>
|
| </div>
|
|
|
| <div class="feature-item">
|
| <div class="feature-icon">🤖</div>
|
| <div class="feature-title">Message Réflexif & Évaluation</div>
|
| <div class="feature-description">
|
| <strong>Évaluation des messages générés par ReflAgent</strong><br>
|
| Analysez les messages auto-réflexifs et évaluez leur qualité selon 5 métriques:
|
| Authenticité Réflexive, Alignement Empathique, Encouragement Sensible au Risque,
|
| Support aux Défis Mentaux et Support Métacognitif.
|
| </div>
|
| </div>
|
|
|
| <div class="feature-item">
|
| <div class="feature-icon">📋</div>
|
| <div class="feature-title">Exemple d'Analyse</div>
|
| <div class="feature-description">
|
| <strong>Cas d'étude avec évaluation détaillée</strong><br>
|
| Découvrez un exemple concret d'analyse d'un étudiant en difficulté, avec le message réflexif
|
| généré, son évaluation métrique et des observations pédagogiques détaillées.
|
| </div>
|
| </div>
|
| </div>
|
|
|
| <div class="how-to-start">
|
| <h4><span>🚀</span> Comment commencer ?</h4>
|
| <div class="step-list">
|
| <div class="step-item">
|
| <strong>Configurez votre profil d'évaluateur</strong>
|
| <p>Accédez à l'onglet "Évaluateur (RGPD)" pour définir vos informations et consentements.</p>
|
| </div>
|
| <div class="step-item">
|
| <strong>Explorez les profils d'apprenants</strong>
|
| <p>Naviguez entre les 14 scénarios d'apprenants différents via les boutons de navigation.</p>
|
| </div>
|
| <div class="step-item">
|
| <strong>Analysez les messages réflexifs</strong>
|
| <p>Évaluez la qualité des messages générés par ReflAgent dans l'onglet "Message Réflexif & Évaluation".</p>
|
| </div>
|
| <div class="step-item">
|
| <strong>Explorer l'exemple d'analyse</strong>
|
| <p>Consultez l'onglet "Exemple d'Analyse" pour comprendre la méthodologie d'évaluation.</p>
|
| </div>
|
| </div>
|
|
|
| <p style="margin-top: 20px; font-style: italic; color: #2E7D32;">
|
| <strong>Conseil :</strong> Commencez par explorer l'exemple d'analyse pour comprendre
|
| comment évaluer les messages avant de procéder à vos propres évaluations.
|
| </p>
|
| </div>
|
|
|
| <div style="text-align: center; margin-top: 40px; padding: 20px; background: #f8f9fa; border-radius: 10px;">
|
| <p style="color: #666; font-size: 14px;">
|
| <strong>Laboratoire d'informatique de l'Université du Mans</strong><br>
|
| Travaux de recherche sur l'apprentissage auto-régulé et l'intelligence artificielle éducative
|
| dans le cadre du projet écri+ :
|
| <a href="https://ecriplus.fr/" target="_blank" style="color: #007bff; text-decoration: none;">
|
| https://ecriplus.fr/
|
| </a>
|
| </p>
|
| </div>
|
|
|
| </div>
|
|
|
|
|
| <div id="tab-evaluator" class="tab-content">
|
| <h3>👤 Informations de l'évaluateur (RGPD)</h3>
|
|
|
| <div class="evaluator-info">
|
|
|
| <div class="evaluator-field">
|
| <label for="gdprConsent">
|
| <strong><span style="color: #1976D2; margin-right: 5px;">🔒</span> Consentement RGPD <span style="color: #e53935;">*</span></strong>
|
| </label>
|
| <div class="gdpr-options">
|
| <label class="gdpr-option">
|
| <input type="radio" name="gdprConsent" value="accept" id="gdprAccept" required>
|
| <span>J'accepte de partager mes informations pour l'évaluation</span>
|
| </label>
|
| <label class="gdpr-option">
|
| <input type="radio" name="gdprConsent" value="decline" id="gdprDecline">
|
| <span>Je préfère rester anonyme</span>
|
| </label>
|
| </div>
|
| <small>Veuillez accepter le consentement RGPD pour pouvoir remplir les champs d'identification</small>
|
| </div>
|
|
|
|
|
| <div id="evaluatorFields" style="display: none;">
|
|
|
| <div class="evaluator-field">
|
| <label for="evaluatorName">
|
| <strong><span style="color: #1976D2; margin-right: 5px;">📝</span> Nom et prénom</strong>
|
| <span style="color: #666; font-size: 13px; font-weight: normal;"> (optionnel)</span>
|
| </label>
|
| <input type="text"
|
| id="evaluatorName"
|
| placeholder="Ex: Dupont Jean ou Marie Curie"
|
| maxlength="100"
|
| disabled>
|
| <small>Veuillez saisir votre nom et prénom si vous souhaitez être identifié</small>
|
| </div>
|
|
|
|
|
| <div class="evaluator-field">
|
| <label for="evaluatorEmail">
|
| <strong><span style="color: #1976D2; margin-right: 5px;">📧</span> Adresse email</strong>
|
| <span style="color: #666; font-size: 13px; font-weight: normal;"> (optionnel)</span>
|
| </label>
|
| <input type="email"
|
| id="evaluatorEmail"
|
| placeholder="votre.email@exemple.fr"
|
| maxlength="100"
|
| disabled>
|
| <small>Pour être contacté concernant les résultats de l'étude</small>
|
| </div>
|
|
|
|
|
| <div class="evaluator-field">
|
| <label for="evaluatorRole"><strong><span style="color: #1976D2; margin-right: 5px;">👔</span> Rôle principal <span style="color: #e53935;">*</span></strong></label>
|
| <select id="evaluatorRole" disabled>
|
| <option value="">Sélectionnez votre rôle...</option>
|
| <option value="enseignant">Enseignant / Formateur</option>
|
| <option value="chercheur">Chercheur / Scientifique</option>
|
| <option value="expert_pedago">Expert pédagogique</option>
|
| <option value="etudiant_avance">Étudiant avancé / Doctorant</option>
|
| <option value="conseiller">Conseiller pédagogique</option>
|
| <option value="responsable">Responsable de formation</option>
|
| <option value="autre">Autre professionnel de l'éducation</option>
|
| </select>
|
| <small>Sélectionnez votre rôle principal dans le domaine éducatif</small>
|
| </div>
|
|
|
|
|
| <div class="evaluator-field">
|
| <label for="messageMastery"><strong><span style="color: #1976D2; margin-right: 5px;">💬</span> Niveau de maîtrise de l'apprentissage auto-régulé <span style="color: #e53935;">*</span></strong></label>
|
| <select id="messageMastery" disabled>
|
| <option value="">Sélectionnez votre niveau...</option>
|
| <option value="novice_srl">Novice – Je découvre l'apprentissage auto-régulé et ses fondements pédagogiques</option>
|
| <option value="intermediaire_srl">Intermédiaire – J'intègre occasionnellement des activités favorisant l'apprentissage auto-régulé</option>
|
| <option value="avance_srl">Avancé – Je conçois et mets en œuvre des dispositifs pédagogiques liés à l'apprentissage auto-régulé, en lien avec mon domaine de recherche</option>
|
| <option value="expert_srl">Expert – Je mène des travaux de recherche et forme d'autres enseignants à l'apprentissage auto-régulé</option>
|
| </select>
|
| <small>Indiquez votre niveau d'expertise dans l'enseignement et la recherche liés à l'apprentissage auto-régulé</small>
|
| </div>
|
|
|
|
|
| <div class="evaluator-field">
|
| <label for="expertiseLevel"><strong><span style="color: #1976D2; margin-right: 5px;">🎓</span> Niveau d'expertise en réflexivité <span style="color: #e53935;">*</span></strong></label>
|
| <select id="expertiseLevel" disabled>
|
| <option value="">Sélectionnez votre niveau...</option>
|
| <option value="debutant">Débutant - Je découvre la réflexivité</option>
|
| <option value="intermediaire">Intermédiaire - J'utilise régulièrement des outils réflexifs</option>
|
| <option value="avance">Avancé - Je conçois des dispositifs réflexifs</option>
|
| <option value="expert">Expert - Je forme à la réflexivité pédagogique</option>
|
| </select>
|
| <small>Indiquez votre niveau de maîtrise des concepts et outils de réflexivité</small>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="anonymousMessage" style="display: none;">
|
| <p>
|
| <strong><span style="margin-right: 5px;">🕵️</span> Évaluation anonyme :</strong> Vos évaluations seront enregistrées sans information personnelle.
|
| Seules vos réponses aux métriques de confiance seront conservées.
|
| </p>
|
| </div>
|
|
|
|
|
| <div style="display: flex; gap: 10px; margin-top: 20px; flex-wrap: wrap;">
|
| <button onclick="fillSampleEvaluator()" type="button" style="background: #666; flex: 1;" id="fillExampleBtn">
|
| <span style="margin-right: 5px;">📋</span> Remplir exemple
|
| </button>
|
| <button onclick="clearEvaluatorFields()" type="button" style="background: #9e9e9e; flex: 1;" id="clearFieldsBtn">
|
| <span style="margin-right: 5px;">🗑️</span> Effacer
|
| </button>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="tab-dashboard" class="tab-content">
|
| <h3>📝 Manifeste étudiant</h3>
|
| <div id="manifest-list">
|
| <div class="manifest-item">
|
| <em>Chargement des données...</em>
|
| </div>
|
| </div>
|
|
|
| <h3> Progression par compétence </h3>
|
| <div id="competence-bars">
|
| <div id="compact-competences">
|
| <em>Chargement des compétences...</em>
|
| </div>
|
| </div>
|
|
|
|
|
| <div class="compact-radar-legend">
|
| <div class="compact-legend-item">
|
| <div class="compact-legend-color compact-legend-low"></div>
|
| <span>Faible (0-50%)</span>
|
| </div>
|
| <div class="compact-legend-item">
|
| <div class="compact-legend-color compact-legend-medium"></div>
|
| <span>Moyen (50-70%)</span>
|
| </div>
|
| <div class="compact-legend-item">
|
| <div class="compact-legend-color compact-legend-high"></div>
|
| <span>Élevé (70-100%)</span>
|
| </div>
|
| </div>
|
|
|
| <h3> Analyse de l'engagement: Indicateurs de comportement d'apprentissage </h3>
|
|
|
|
|
| <div class="compact-radar-metrics-grid" id="compact-radar-metrics-grid">
|
|
|
| </div>
|
|
|
|
|
| <div id="radar-container">
|
| <div style="display: flex; gap: 20px; flex-wrap: wrap;">
|
|
|
| <div style="flex: 1; min-width: 300px; text-align: center;">
|
| <canvas id="radar" width="500" height="500" style="max-width: 100%; height: auto;"></canvas>
|
| </div>
|
|
|
|
|
| <div class="compact-radar-bot-message" style="flex: 1; min-width: 300px;">
|
| <div class="compact-radar-bot-header">
|
| <h4 class="compact-radar-bot-title">Analyse du radar des métriques d'engagement</h4>
|
| </div>
|
| <p class="compact-radar-bot-content" id="compact-radar-bot-content">Analyse en cours...</p>
|
| <div class="compact-radar-bot-insights">
|
| <div id="compact-radar-bot-insights">
|
|
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div class="audio-narration-compact" id="radarAudioContainer">
|
| <div class="audio-icon">
|
| <span>🎙️</span>
|
| <span>Radar</span>
|
| </div>
|
| <div class="audio-controls">
|
| <button class="audio-btn" id="playRadarAudioBtn" onclick="playRadarNarration()">▶️</button>
|
| <button class="audio-btn" id="pauseRadarAudioBtn" onclick="pauseRadarNarration()">⏸️</button>
|
| <button class="audio-btn" id="stopRadarAudioBtn" onclick="stopRadarNarration()">⏹️</button>
|
| <div class="audio-progress" id="radarAudioProgress">
|
| <div class="audio-progress-fill" id="radarAudioProgressFill"></div>
|
| </div>
|
| <span class="audio-time" id="radarAudioTime">00:00</span>
|
| </div>
|
| <div class="audio-status" id="radarAudioStatus">Prêt</div>
|
| </div>
|
|
|
|
|
| <div class="compact-heatmap-and-indicators">
|
| <h3>🔥 Heatmap d'activité - Analyse de la persistance et du management de l'effort (persévérance)</h3>
|
|
|
| <div class="compact-heatmap-container">
|
|
|
| <div class="compact-heatmap-left">
|
| <div class="compact-heatmap-analysis">
|
| <div class="compact-analysis-controls">
|
| <label for="persistenceMode">Mode d'analyse :</label>
|
| <select id="persistenceMode" onchange="changePersistenceAnalysis()">
|
| <option value="regularity">📊 Régularité du travail</option>
|
| <option value="effortPattern">🔄 Schéma d'effort</option>
|
| <option value="deadline">⏰ Gestion des échéances</option>
|
| <option value="combined" selected>🎯 Vue combinée</option>
|
| </select>
|
| </div>
|
|
|
|
|
| <canvas id="heatmap" width="800" height="350" style="max-width: 100%; height: auto;"></canvas>
|
|
|
|
|
| <div class="compact-enriched-legend">
|
| <div class="compact-legend-section">
|
| <h5 style="margin: 0 0 10px 0; font-size: 14px; color: #1976D2; display: flex; align-items: center; gap: 6px;">
|
| <span>📈</span> Niveaux d'activité
|
| </h5>
|
| <div class="compact-legend-grid">
|
| <div class="compact-legend-item-small">
|
| <div class="compact-legend-color-small" style="background:#EBEDF0;"></div>
|
| <span>Aucune</span>
|
| </div>
|
| <div class="compact-legend-item-small">
|
| <div class="compact-legend-color-small" style="background:#C6E48B;"></div>
|
| <span>Faible</span>
|
| </div>
|
| <div class="compact-legend-item-small">
|
| <div class="compact-legend-color-small" style="background:#7BC96F;"></div>
|
| <span>Moyenne</span>
|
| </div>
|
| <div class="compact-legend-item-small">
|
| <div class="compact-legend-color-small" style="background:#239A3B;"></div>
|
| <span>Élevée</span>
|
| </div>
|
| <div class="compact-legend-item-small">
|
| <div class="compact-legend-color-small" style="background:#196127;"></div>
|
| <span>Intense</span>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div class="compact-heatmap-right">
|
| <div class="compact-persistence-analysis" id="compact-persistenceAnalysis">
|
| <h5 style="margin: 0 0 15px 0; font-size: 14px; color: #1976D2; display: flex; align-items: center; gap: 6px;">
|
| <span>🕖</span> Indicateurs de la gestion du temps et régularité
|
| </h5>
|
| <div class="compact-persistence-indicators">
|
| <div class="compact-indicator" id="regularity-indicator">
|
| <span class="compact-indicator-dot" style="background:#FF6B6B;"></span>
|
| <span>
|
| Régularité du travail :
|
| <strong id="compact-regularityScore">-</strong>
|
| </span>
|
| </div>
|
|
|
| <div style="margin-left: 18px; margin-top: 0; font-size: 12px; color: #888;" id="regularity-description">
|
| La constance de l'activité de l'apprenant dans le temps.
|
| </div>
|
|
|
| <div class="compact-indicator" id="deadline-indicator">
|
| <span class="compact-indicator-dot" style="background:#FFD166;"></span>
|
| <span>Gestion des échéances : <strong id="compact-deadlineScore">-</strong></span>
|
| </div>
|
|
|
| <div style="margin-left: 18px; margin-top: 0; font-size: 12px; color: #888;" id="deadline-description">
|
| La capacité de l'apprenant à respecter les délais.
|
| </div>
|
|
|
| <div class="compact-indicator" style="margin-top: 10px;" id="effort-indicator">
|
| <span class="compact-indicator-dot" style="background:#4ECDC4;"></span>
|
| <span>
|
| <strong>Schéma d'effort :</strong>
|
| <span id="compact-effortPattern">-</span>
|
| </span>
|
| </div>
|
|
|
| <div style="margin-left: 18px; margin-top: 0; font-size: 12px; color: #888;" id="effort-description">
|
| La dynamique temporelle de l'effort.
|
| </div>
|
| </div>
|
|
|
| <div style="text-align: center; margin-top: 15px;">
|
| <strong>Persistance et gestion des efforts :</strong>
|
| <span id="compact-regularityText">Analyse en cours...</span>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div class="audio-narration-compact" id="heatmapAudioContainer">
|
| <div class="audio-icon">
|
| <span>🎙️</span>
|
| <span>Heatmap</span>
|
| </div>
|
| <div class="audio-controls">
|
| <button class="audio-btn" id="playHeatmapAudioBtn" onclick="playHeatmapNarration()">▶️</button>
|
| <button class="audio-btn" id="pauseHeatmapAudioBtn" onclick="pauseHeatmapNarration()">⏸️</button>
|
| <button class="audio-btn" id="stopHeatmapAudioBtn" onclick="stopHeatmapNarration()">⏹️</button>
|
| <div class="audio-progress" id="heatmapAudioProgress">
|
| <div class="audio-progress-fill" id="heatmapAudioProgressFill"></div>
|
| </div>
|
| <span class="audio-time" id="heatmapAudioTime">00:00</span>
|
| </div>
|
| <div class="audio-status" id="heatmapAudioStatus">Prêt</div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="tab-evaluation" class="tab-content">
|
| <h3>🤖 ReflAgent – Analyse & accompagnement</h3>
|
| <div id="reflagent">
|
| <em>Le message d'analyse apparaîtra ici après chargement...</em>
|
| </div>
|
|
|
| <hr>
|
|
|
| <h3>🧑⚖️ Volet Expert – Métriques de Confiance</h3>
|
| <p style="color: #666; margin-bottom: 20px; font-style: italic;">
|
| Évaluez votre confiance dans l'analyse de ReflAgent pour ce scénario :
|
| </p>
|
|
|
|
|
| <div class="trust-item">
|
| <b>Authenticité Réflexive (AR)</b>
|
| <div class="stars" data-metric="AR">
|
|
|
| </div>
|
| <small style="color: #666; display: block; margin-top: 5px;">
|
| Le message auto-réflexif reflète-t-il fidèlement la situation réelle de l'étudiant (profil d'apprenant) ?
|
| </small>
|
| </div>
|
|
|
| <div class="trust-item">
|
| <b>Alignement Empathique (AE)</b>
|
| <div class="stars" data-metric="AE">
|
|
|
| </div>
|
| <small style="color: #666; display: block; margin-top: 5px;">
|
| Le message auto-réflexif inclut-il des marques linguistiques empathiques ?
|
| </small>
|
| </div>
|
|
|
| <div class="trust-item">
|
| <b>Encouragement Sensible au Risque (ESR)</b>
|
| <div class="stars" data-metric="ESR">
|
|
|
| </div>
|
| <small style="color: #666; display: block; margin-top: 5px;">
|
| Le message auto-réflexif montre un équilibre harmonieux entre les encouragements et l'indication du niveau de risque de l'apprenant ?
|
| </small>
|
| </div>
|
|
|
| <div class="trust-item">
|
| <b>Support aux Défis Mentaux (SDM)</b>
|
| <div class="stars" data-metric="SDM">
|
|
|
| </div>
|
| <small style="color: #666; display: block; margin-top: 5px;">
|
| Le message auto-réflexif stimule l'étudiant et le rend compétitif ?
|
| </small>
|
| </div>
|
|
|
| <div class="trust-item">
|
| <b>Support Métacognitif (SM)</b>
|
| <div class="stars" data-metric="SM">
|
|
|
| </div>
|
| <small style="color: #666; display: block; margin-top: 5px;">
|
| Le message auto-réflexif aide-t-il l'étudiant à réfléchir sur ses stratégies d'apprentissage et sa méthode de travail sur la plateforme ?
|
| </small>
|
| </div>
|
|
|
| <h4>💬 Commentaire expert</h4>
|
| <textarea id="trustComment" placeholder="Ajoutez vos observations, suggestions ou critiques concernant l'analyse de ReflAgent..."></textarea>
|
|
|
| <div style="display: flex; justify-content: space-between; align-items: center; margin: 25px 0; flex-wrap: wrap; gap: 20px;">
|
| <div style="flex-grow: 1; min-width: 300px;">
|
| <h4 style="margin-bottom: 10px;">🔒 Indice global de confiance</h4>
|
| <div class="progress-container">
|
| <div id="trustBar">0%</div>
|
| </div>
|
| <div style="display: flex; justify-content: space-between; margin-top: 5px; font-size: 12px; color: #666;">
|
| <span>Faible confiance</span>
|
| <span>Confidence moyenne</span>
|
| <span>Forte confiance</span>
|
| </div>
|
| </div>
|
| <div style="display: flex; flex-direction: column; gap: 10px; align-items: flex-end; min-width: 200px;">
|
| <button id="saveTrustBtn" style="height: fit-content; width: 100%;">
|
| 💾 Sauvegarder l'évaluation
|
| </button>
|
|
|
| <button
|
| id="crossReadersBtn"
|
| style="height: fit-content; width: 100%; background-color: #ccc; color: #666; cursor: not-allowed;"
|
| disabled
|
| >
|
| 📊 Lecture croisée
|
| </button>
|
| </div>
|
|
|
| </div>
|
|
|
| <div id="saveTrustMsg"></div>
|
|
|
|
|
| <div class="stats-grid">
|
| <div class="stat-item">
|
| <div class="stat-label">Scénario actuel</div>
|
| <div class="stat-value" id="currentScenarioNum">-</div>
|
| </div>
|
| <div class="stat-item">
|
| <div class="stat-label">Confiance moyenne</div>
|
| <div class="stat-value" id="avgTrustScore">0%</div>
|
| </div>
|
| <div class="stat-item">
|
| <div class="stat-label">Niveau de risque</div>
|
| <div class="stat-value" id="riskLevel">-</div>
|
| </div>
|
| <div class="stat-item">
|
| <div class="stat-label">Activité moyenne</div>
|
| <div class="stat-value" id="avgActivity">-</div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div id="tab-example" class="tab-content">
|
| <h3>📋 Exemple d'Analyse – Étudiant en difficulté / évitement de l'échec : peur de l'échec supérieure à la motivation de réussite.</h3>
|
|
|
| <div class="example-separator"></div>
|
|
|
| <div class="example-analysis-box">
|
| <h4> Éléments clés de l'analyse du profil de l'apprenant</h4>
|
| <ul>
|
| <li>
|
| <strong>Profil global :</strong><br>
|
| Étudiant à risque, faible engagement et compétences fragiles.
|
| </li>
|
| <br>
|
| <li>
|
| <strong>Points forts :</strong><br>
|
| Volonté minimale de progresser (essayer malgré l'échec), possibilité de reconstruire la motivation par petites actions.
|
| </li>
|
| <br>
|
| <li>
|
| <strong>Points à améliorer :</strong><br>
|
| Niveau d'activité et d'implication, Organisation et stratégies d'apprentissage.
|
| </li>
|
| <br>
|
| <li>
|
| <strong>Objectif pédagogique :</strong><br>
|
| Réintroduire l'étudiant dans un rythme régulier avec des objectifs accessibles, renforcer la confiance et la motivation, fournir un soutien plus concret.
|
| </li>
|
| </ul>
|
|
|
| </div>
|
|
|
| <div class="example-analysis-box">
|
| <h4>Message auto-réflexif</h4>
|
| Ton niveau d'engagement est actuellement très faible : seulement 35 % des activités ont été démarrées et 30 % achevées. 😔 Tes compétences restent fragiles (40 %), ce qui indique un risque élevé de décrochage.
|
| Tu sembles parfois éviter les situations qui pourraient mener à l'échec, mais il est important de te rappeler que l'échec fait partie de l'apprentissage et peut devenir une véritable source de progression. 🛡️
|
| Commence par fixer des objectifs minuscules et accessibles, et entreprends de petites actions régulières dès le début de la semaine. Cela te permettra de reconstruire progressivement un rythme stable et de retrouver confiance et motivation.
|
| Tu dois travailler les compétences mises en avant : la compétence Favoriser la progression du domaine Paragraphe et la compétence Valoriser les petites victoires du domaine Texte.
|
| </div>
|
|
|
|
|
|
|
| <div class="example-separator"></div>
|
|
|
| <div class="example-analysis-box">
|
| <h4> Évaluation métrique avec observations</h4>
|
| <table class="example-metrics-table">
|
| <thead>
|
| <tr>
|
| <th width="25%">Métrique</th>
|
| <th width="15%">Niveau ★</th>
|
| <th width="60%">Observations (avec passage du message)</th>
|
| </tr>
|
| </thead>
|
| <tbody>
|
| <tr>
|
| <td><strong>Authenticité Réflexive (AR)</strong></td>
|
| <td><span class="metric-stars">★★★★☆</span></td>
|
| <td class="metric-observation">
|
| <span class="success">L'analyse reflète fidèlement la situation :</span> « Ton niveau d'engagement est actuellement très faible … Tes compétences restent fragiles » ✅
|
| </td>
|
| </tr>
|
| <tr>
|
| <td><strong>Alignement Empathique (AE)</strong></td>
|
| <td><span class="metric-stars">★★★☆☆</span></td>
|
| <td class="metric-observation">
|
| <span class="warning">L'agent montre une compréhension partielle des émotions (peur de l'échec supérieure à la motivation de réussite) :</span> « Tu sembles parfois éviter les situations qui pourraient mener à l'échec » ⚠️ Peut être renforcé avec plus de soutien émotionnel direct
|
| </td>
|
| </tr>
|
| <tr>
|
| <td><strong>Encouragement Sensible au Risque (ESR)</strong></td>
|
| <td><span class="metric-stars">★☆☆☆☆</span></td>
|
| <td class="metric-observation">
|
| <span class="error">L'agent indique le risque mais le soutien reste limité :</span> « …ce qui indique un risque élevé de décrochage » ❌ Faible guidance concrète pour sécuriser la progression
|
| </td>
|
| </tr>
|
| <tr>
|
| <td><strong>Support aux Défis Mentaux (SDM)</strong></td>
|
| <td><span class="metric-stars">★☆☆☆☆</span></td>
|
| <td class="metric-observation">
|
| <span class="error">Usage très limité de défis mentaux comme stimulus et de compétition :</span> « Commence par fixer des objectifs minuscules et accessibles » ❌ Absence de stratégies autour des défis mentaux.
|
| </td>
|
| </tr>
|
| <tr>
|
| <td><strong>Support Métacognitif (SM)</strong></td>
|
| <td><span class="metric-stars">★★☆☆☆</span></td>
|
| <td class="metric-observation">
|
| <span class="warning">Encouragement minimal à réfléchir sur sa méthode, Suggestions très limitées pour développer la réflexion ou les compétences :</span> « entreprends de petites actions régulières » ⚠️ Peu d'indication sur planification ou révision de stratégie
|
| </td>
|
| </tr>
|
| </tbody>
|
| </table>
|
| </div>
|
|
|
| </div>
|
| </div>
|
| </div>
|
|
|
| <script>
|
|
|
| let scenarios = [];
|
| let currentScenarioIndex = 0;
|
| let radarMetrics = [];
|
|
|
|
|
| let radarAudio = null;
|
| let heatmapAudio = null;
|
| let currentRadarAudioSrc = "";
|
| let currentHeatmapAudioSrc = "";
|
|
|
|
|
| const DEFAULT_RADAR_METRICS = [
|
| { label: "Démarrage des activités", value: 85 },
|
| { label: "Éléments des connaissances validées", value: 72 },
|
| { label: "Niveau moyen de compétence", value: 68 },
|
| { label: "Taux d'erreur", value: 35 },
|
| { label: "Achèvement des activités", value: 74 },
|
| { label: "Interactions avec les ressources", value: 80 },
|
| { label: "Score", value: 78 }
|
| ];
|
|
|
|
|
| const trustMetrics = {
|
| "AR": 0,
|
| "AE": 0,
|
| "ESR": 0,
|
| "SDM": 0,
|
| "SM": 0
|
| };
|
|
|
| const trustWeights = {
|
| "AR": 0.30,
|
| "AE": 0.20,
|
| "ESR": 0.20,
|
| "SDM": 0.10,
|
| "SM": 0.20
|
| };
|
|
|
|
|
| const GOOGLE_SCRIPT_URL = 'https://script.google.com/macros/s/AKfycbyB_Q1RH9IctsE_jEbZUmyxv4WXlpGFFgtyEUsLmV72W3htK1YO3GSeoyjQIoWCKEod/exec';
|
|
|
|
|
| const DEFAULT_SCENARIOS = [
|
| { 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" } },
|
| { 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" } },
|
| { id: 3, title: "Étudiant orienté vers le succès", manifest: { type: "Performance orientée", manifeste: "Je vise l'excellence dans tout ce que je fais", description: "Très orienté vers les résultats et la réussite" } },
|
| { id: 4, title: "Étudiant motivé", manifest: { type: "Motivation soutenue", manifeste: "Je suis déterminé à réussir ce cours", description: "Bonne motivation avec des objectifs clairs" } },
|
| { id: 5, title: "Étudiant surmotivé", manifest: { type: "Surinvestissement", manifeste: "Je passe trop de temps sur le cours au détriment du reste", description: "Investissement excessif pouvant mener à l'épuisement" } },
|
| { id: 6, title: "Étudiant stratégique", manifest: { type: "Approche calculée", manifeste: "Je choisis les activités qui rapportent le plus de points", description: "Approche rationnelle et ciblée de l'apprentissage" } },
|
| { id: 7, title: "Étudiant en amélioration", manifest: { type: "Progression constante", manifeste: "Je vois mes progrès semaine après semaine", description: "Évolution positive des compétences et résultats" } },
|
| { id: 8, title: "Étudiant en difficulté", manifest: { type: "Difficultés persistantes", manifeste: "J'ai du mal à comprendre malgré mes efforts", description: "Rencontre des obstacles d'apprentissage importants" } },
|
| { id: 9, title: "Étudiant évitant l'échec", manifest: { type: "Évitement", manifeste: "J'ai peur de me tromper donc je ne tente pas", description: "Anxiété face à l'échec limitant les tentatives" } },
|
| { id: 10, title: "Étudiant à risque", manifest: { type: "Risque d'abandon", manifeste: "Je pense abandonner le cours", description: "Très faible engagement et motivation" } },
|
| { 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" } },
|
| { 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" } },
|
| { id: 13, title: "Étudiant inactif", manifest: { type: "Inactivité", manifeste: "Je ne trouve pas la motivation pour commencer", description: "Très faible participation et engagement" } },
|
| { 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" } },
|
| { 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" } },
|
| { id: 16, title: "Étudiant actif", manifest: { type: "Actif", manifeste: "Je suis très actif sur la plateforme", description: "Forte implication et nombreux efforts" } }
|
| ];
|
|
|
|
|
| const perseveranceProfiles = {
|
| "Étudiant engagé": {
|
| level: "Très élevée",
|
| interpretation: "Efforts constants, persévère même face aux difficultés",
|
| color: "#43A047",
|
| regularity: 90,
|
| deadline: 88,
|
| effortPattern: "Effort concentré (Pic d'activité jeudi/vendredi)"
|
| },
|
| "Étudiant actif mais inefficace": {
|
| level: "Moyenne",
|
| interpretation: "Efforts importants mais mal régulés, persévérance peu productive",
|
| color: "#FB8C00",
|
| regularity: 55,
|
| deadline: 44,
|
| effortPattern: "Travail weekend (Activité principalement le weekend)"
|
| },
|
| "Étudiant orienté vers le succès": {
|
| level: "Élevée",
|
| interpretation: "Persévérance principalement guidée par l'atteinte des objectifs",
|
| color: "#4CAF50",
|
| regularity: 75,
|
| deadline: 66,
|
| effortPattern: "Régulier (Effort équilibré toute la semaine)"
|
| },
|
| "Étudiant motivé": {
|
| level: "Élevée",
|
| interpretation: "Engagement soutenu et continuité stable de l'effort",
|
| color: "#4CAF50",
|
| regularity: 75,
|
| deadline: 66,
|
| effortPattern: "Régulier (Effort équilibré toute la semaine)"
|
| },
|
| "Étudiant surmotivé": {
|
| level: "Très élevée",
|
| interpretation: "Effort intense, parfois excessif, avec risque de surcharge",
|
| color: "#43A047",
|
| regularity: 90,
|
| deadline: 91,
|
| effortPattern: "Régulier (Effort équilibré toute la semaine)"
|
| },
|
| "Étudiant stratégique": {
|
| level: "Élevée",
|
| interpretation: "Effort bien dosé, persévérance optimisée selon le rendement attendu",
|
| color: "#4CAF50",
|
| regularity: 75,
|
| deadline: 66,
|
| effortPattern: "Régulier (Effort équilibré toute la semaine)"
|
| },
|
| "Étudiant en amélioration": {
|
| level: "Moyenne à élevée",
|
| interpretation: "Efforts croissants, persévérance en cours de structuration",
|
| color: "#FF9800",
|
| regularity: 55,
|
| deadline: 50,
|
| effortPattern: "Travail weekend (Activité principalement le weekend)"
|
| },
|
| "Étudiant en difficulté": {
|
| level: "Faible",
|
| interpretation: "Découragement fréquent et difficulté à maintenir l'effort",
|
| color: "#E53935",
|
| regularity: 35,
|
| deadline: 13,
|
| effortPattern: "Très faible (Activité minimale toute la semaine)"
|
| },
|
| "Étudiant évitant l'échec": {
|
| level: "Moyenne",
|
| interpretation: "Persévérance motivée par la peur de l'échec plutôt que par l'apprentissage",
|
| color: "#FB8C00",
|
| regularity: 55,
|
| deadline: 19,
|
| effortPattern: "Effort concentré (Pic d'activité jeudi/vendredi)"
|
| },
|
| "Étudiant à risque": {
|
| level: "Très faible",
|
| interpretation: "Abandon rapide et très faible tolérance à l'effort",
|
| color: "#C62828",
|
| regularity: 20,
|
| deadline: 9,
|
| effortPattern: "Très faible (Activité minimale toute la semaine)"
|
| },
|
| "Étudiant en progression": {
|
| level: "Élevée",
|
| interpretation: "Efforts réguliers et de mieux en mieux maîtrisés",
|
| color: "#4CAF50",
|
| regularity: 75,
|
| deadline: 47,
|
| effortPattern: "Très faible (Activité minimale toute la semaine)"
|
| },
|
| "Étudiant acceptant l'échec": {
|
| level: "Élevée",
|
| interpretation: "Bonne résilience, persévère malgré les erreurs et les échecs",
|
| color: "#4CAF50",
|
| regularity: 75,
|
| deadline: 47,
|
| effortPattern: "Régulier (Effort équilibré toute la semaine)"
|
| },
|
| "Étudiant inactif": {
|
| level: "Très faible",
|
| interpretation: "Manque d'engagement, difficulté à initier et maintenir l'effort",
|
| color: "#C62828",
|
| regularity: 20,
|
| deadline: 0,
|
| effortPattern: "Très faible (Activité minimale toute la semaine)"
|
| },
|
| "Étudiant non engagé": {
|
| level: "Faible",
|
| interpretation: "Manque de motivation, faible persévérance dans l'effort",
|
| color: "#E53935",
|
| regularity: 35,
|
| deadline: 3,
|
| effortPattern: "Très faible (Activité minimale toute la semaine)"
|
| },
|
| "Étudiant persévérant": {
|
| level: "Moyenne à élevée",
|
| interpretation: "Efforts maintenus malgré les doutes, persévérance réelle mais freinée par le manque de confiance",
|
| color: "#FF9800",
|
| regularity: 55,
|
| deadline: 56,
|
| effortPattern: "Accélération progressive (Démarrage lent, fin forte)"
|
| },
|
| "Étudiant actif": {
|
| level: "Élevée",
|
| interpretation: "Forte implication et nombreux efforts, mais difficulté à maintenir l'énergie jusqu'au bout",
|
| color: "#4CAF50",
|
| regularity: 75,
|
| deadline: 41,
|
| effortPattern: "Régulier (Effort équilibré toute la semaine)"
|
| }
|
| };
|
|
|
|
|
| const profileMessages = {
|
| "Étudiant engagé": {
|
| title: "Démarrage Rapide & Engagement Soutenu",
|
| message: "Tu démarres 85% des activités avec enthousiasme et les termines à 74% ! Ton interaction avec les ressources (80%) montre une implication active.",
|
| insights: [
|
| { icon: "🚀", text: "Démarrage élevé (85%)" },
|
| { icon: "✅", text: "Achèvement solide (74%)" },
|
| { icon: "📚", text: "Interaction soutenue (80%)" }
|
| ]
|
| },
|
| "Étudiant actif mais inefficace": {
|
| title: "Activité Intense mais Performance Perfectible",
|
| message: " Tu interagis beaucoup avec les ressources (85%) mais ton taux de réussite reste à 65% seulement. La qualité prime sur la quantité.",
|
| insights: [
|
| { icon: "🔄", text: "Interactions maximales (85%)" },
|
| { icon: "📉", text: "Score modéré (65%)" },
|
| { icon: "🎯", text: "Concentration requise" }
|
| ]
|
| },
|
| "Étudiant orienté vers le succès": {
|
| title: "Excellence dans l'Action",
|
| message: "Tu excelles dans le démarrage (90%) ET l'achèvement (90%) des activités ! Ton score de 85% reflète une implication exceptionnelle.",
|
| insights: [
|
| { icon: "⭐", text: "Démarrage maximal (90%)" },
|
| { icon: "✅", text: "Achèvement parfait (90%)" },
|
| { icon: "📈", text: "Performance élevée (85%)" }
|
| ]
|
| },
|
| "Étudiant motivé": {
|
| title: "Premiers Pas Encourageants",
|
| message: "Tu commences 65% des activités avec curiosité ! Ton interaction avec les ressources (70%) montre une belle ouverture d'esprit.",
|
| insights: [
|
| { icon: "🌟", text: "Démarrage encourageant (65%)" },
|
| { icon: "📖", text: "Engagement actif (70%)" },
|
| { icon: "🧱", text: "Compétences en développement" }
|
| ]
|
| },
|
| "Étudiant surmotivé": {
|
| title: "Surinvestissement dans l'Action",
|
| message: "Ton implication est exceptionnelle : 98% d'interaction avec les ressources ! Mais attention à l'équilibre pour éviter l'épuisement.",
|
| insights: [
|
| { icon: "⚡", text: "Interaction extrême (98%)" },
|
| { icon: "🚀", text: "Démarrage quasi-parfait (95%)" },
|
| { icon: "⚖️", text: "Équilibre nécessaire" }
|
| ]
|
| },
|
| "Étudiant stratégique": {
|
| title: "Action Réfléchie et Ciblée",
|
| message: "Tu achèves 75% des activités avec seulement 55% d'interaction. Preuve d'une approche intelligente et efficiente.",
|
| insights: [
|
| { icon: "🧠", text: "Efficience démontrée" },
|
| { icon: "✅", text: "Bon achèvement (75%)" },
|
| { icon: "📊", text: "Ressources ciblées (55%)" }
|
| ]
|
| },
|
| "Étudiant en amélioration": {
|
| title: "Progression dans l'Action",
|
| message: "Tu démarres 70% des activités et les termines à 68%. Une progression régulière et encourageante !",
|
| insights: [
|
| { icon: "🔄", text: "Démarrage constant (70%)" },
|
| { icon: "📝", text: "Achèvement régulier (68%)" },
|
| { icon: "🎨", text: "Trajectoire d'apprentissage prometteuse" }
|
| ]
|
| },
|
| "Étudiant en difficulté": {
|
| title: "Approche Collaborative Active",
|
| message: "Tu interagis beaucoup (85%) et démarres 72% des activités. Ta force réside dans l'apprentissage social.",
|
| insights: [
|
| { icon: "👥", text: "Interactions élevées (85%)" },
|
| { icon: "🚀", text: "Démarrage solide (72%)" },
|
| { icon: "💬", text: "Taux d'erreurs observées" }
|
| ]
|
| },
|
| "Étudiant évitant l'échec": {
|
| title: "Démarrage Hésitant",
|
| message: "Seulement 35% des activités sont commencées, et 30% terminées. Chaque petit pas d'action compte.",
|
| insights: [
|
| { icon: "😨", text: "Démarrage faible (35%)" },
|
| { icon: "⏱️", text: "Achèvement limité (30%)" },
|
| { icon: "🌱", text: "Niveau d'activité et d'engagement limité" }
|
| ]
|
| },
|
| "Étudiant à risque": {
|
| title: "Action Inconstante",
|
| message: "Tu commences 75% des activités mais n'en achèves que 55%. La régularité dans l'action te serait bénéfique.",
|
| insights: [
|
| { icon: "📉", text: "Inconstance d'achèvement" },
|
| { icon: "🚀", text: "Démarrage bon (75%)" },
|
| { icon: "⚙️", text: "Continuité à développer" }
|
| ]
|
| },
|
| "Étudiant en progression": {
|
| title: "Action Techniquement Maîtrisée",
|
| message: "Tu démontres une belle constance : 70% de démarrage, 68% d'achèvement, et un score de 78% !",
|
| insights: [
|
| { icon: "🔧", text: "Un apprentissage de plus en plus maîtrisé" },
|
| { icon: "📊", text: "Score élevé (78%)" },
|
| { icon: "🔄", text: "Constance démontrée" }
|
| ]
|
| },
|
| "Étudiant acceptant l'échec": {
|
| title: "Planification vs Action",
|
| message: "Tu planifies bien (85% de démarrage) mais l'achèvement reste à 58%. L'action prime sur la perfection.",
|
| insights: [
|
| { icon: "📋", text: "Planification solide (85%)" },
|
| { icon: "⚡", text: "Action à intensifier" },
|
| { icon: "✅", text: "Achèvement perfectible (58%)" }
|
| ]
|
| },
|
| "Étudiant inactif": {
|
| title: "Paralysie de l'Action",
|
| message: "Seulement 15% des activités sont commencées. Le premier pas d'action est le plus important.",
|
| insights: [
|
| { icon: "😰", text: "Démarrage minimal (15%)" },
|
| { icon: "🐌", text: "Achèvement faible (10%)" },
|
| { icon: "✨", text: "Difficultés à choisir, démarrer et compléter une activité" }
|
| ]
|
| },
|
| "Étudiant non engagé": {
|
| title: "Reprise de l'Action",
|
| message: "Après un échec, seulement 30% des activités sont commencées. Chaque nouvelle action est une nouvelle chance.",
|
| insights: [
|
| { icon: "😔", text: "Démarrage faible (30%)" },
|
| { icon: "📉", text: "Achèvement bas (25%)" },
|
| { icon: "🔄", text: "Redémarrage progressif" }
|
| ]
|
| },
|
| "Étudiant persévérant": {
|
| title: "Efforts Réels malgré le Doute",
|
| 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.",
|
| insights: [
|
| { icon: "🌱", text: "Efforts constants malgré les doutes" },
|
| { icon: "🧠", text: "Compétences bien présentes (66%)" },
|
| { icon: "💪", text: "Persévérance visible" }
|
| ]
|
| },
|
| "Étudiant actif": {
|
| title: "Engagement Fort mais Énergie à Préserver",
|
| 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.",
|
| insights: [
|
| { icon: "⚡", text: "Engagement élevé dès le départ (85%)" },
|
| { icon: "📚", text: "Usage fréquent des ressources (75%)" },
|
| { icon: "🧘", text: "Besoin de mieux doser l'effort" }
|
| ]
|
| }
|
| };
|
|
|
|
|
|
|
|
|
| function getRadarAudioPath(scenarioId) {
|
| return `static/audio/radar_${scenarioId}.mp3`;
|
| }
|
|
|
|
|
| function getHeatmapAudioPath(scenarioId) {
|
| return `static/audio/heatmap_${scenarioId}.mp3`;
|
| }
|
| function initAudioElements() {
|
| radarAudio = new Audio();
|
| heatmapAudio = new Audio();
|
|
|
| radarAudio.addEventListener('timeupdate', function() {
|
| if (radarAudio.duration) {
|
| const percent = (radarAudio.currentTime / radarAudio.duration) * 100;
|
| const fill = document.getElementById('radarAudioProgressFill');
|
| if (fill) fill.style.width = percent + '%';
|
| const timeEl = document.getElementById('radarAudioTime');
|
| if (timeEl) {
|
| timeEl.textContent = formatTime(radarAudio.currentTime);
|
| }
|
| }
|
| });
|
|
|
| radarAudio.addEventListener('ended', function() {
|
| const statusEl = document.getElementById('radarAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Terminé';
|
| const fill = document.getElementById('radarAudioProgressFill');
|
| if (fill) fill.style.width = '0%';
|
| });
|
|
|
| radarAudio.addEventListener('play', function() {
|
| const statusEl = document.getElementById('radarAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Lecture...';
|
| });
|
|
|
| radarAudio.addEventListener('pause', function() {
|
| const statusEl = document.getElementById('radarAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Pause';
|
| });
|
|
|
| heatmapAudio.addEventListener('timeupdate', function() {
|
| if (heatmapAudio.duration) {
|
| const percent = (heatmapAudio.currentTime / heatmapAudio.duration) * 100;
|
| const fill = document.getElementById('heatmapAudioProgressFill');
|
| if (fill) fill.style.width = percent + '%';
|
| const timeEl = document.getElementById('heatmapAudioTime');
|
| if (timeEl) {
|
| timeEl.textContent = formatTime(heatmapAudio.currentTime);
|
| }
|
| }
|
| });
|
|
|
| heatmapAudio.addEventListener('ended', function() {
|
| const statusEl = document.getElementById('heatmapAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Terminé';
|
| const fill = document.getElementById('heatmapAudioProgressFill');
|
| if (fill) fill.style.width = '0%';
|
| });
|
|
|
| heatmapAudio.addEventListener('play', function() {
|
| const statusEl = document.getElementById('heatmapAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Lecture...';
|
| });
|
|
|
| heatmapAudio.addEventListener('pause', function() {
|
| const statusEl = document.getElementById('heatmapAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Pause';
|
| });
|
|
|
| const radarProgress = document.getElementById('radarAudioProgress');
|
| if (radarProgress) {
|
| radarProgress.addEventListener('click', function(e) {
|
| if (radarAudio.duration) {
|
| const rect = this.getBoundingClientRect();
|
| const percent = (e.clientX - rect.left) / rect.width;
|
| radarAudio.currentTime = percent * radarAudio.duration;
|
| }
|
| });
|
| }
|
|
|
| const heatmapProgress = document.getElementById('heatmapAudioProgress');
|
| if (heatmapProgress) {
|
| heatmapProgress.addEventListener('click', function(e) {
|
| if (heatmapAudio.duration) {
|
| const rect = this.getBoundingClientRect();
|
| const percent = (e.clientX - rect.left) / rect.width;
|
| heatmapAudio.currentTime = percent * heatmapAudio.duration;
|
| }
|
| });
|
| }
|
| }
|
|
|
| function formatTime(seconds) {
|
| if (isNaN(seconds)) return '00:00';
|
| const mins = Math.floor(seconds / 60);
|
| const secs = Math.floor(seconds % 60);
|
| return mins.toString().padStart(2, '0') + ':' + secs.toString().padStart(2, '0');
|
| }
|
|
|
| function loadRadarAudioForScenario(scenarioId) {
|
| if (!radarAudio) initAudioElements();
|
| const audioPath = getRadarAudioPath(scenarioId);
|
| currentRadarAudioSrc = audioPath;
|
| radarAudio.src = audioPath;
|
| radarAudio.load();
|
| const statusEl = document.getElementById('radarAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Prêt';
|
| const timeEl = document.getElementById('radarAudioTime');
|
| if (timeEl) timeEl.textContent = '00:00';
|
| const fill = document.getElementById('radarAudioProgressFill');
|
| if (fill) fill.style.width = '0%';
|
| }
|
|
|
| function loadHeatmapAudioForScenario(scenarioId) {
|
| if (!heatmapAudio) initAudioElements();
|
| const audioPath = getHeatmapAudioPath(scenarioId);
|
| currentHeatmapAudioSrc = audioPath;
|
| heatmapAudio.src = audioPath;
|
| heatmapAudio.load();
|
| const statusEl = document.getElementById('heatmapAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Prêt';
|
| const timeEl = document.getElementById('heatmapAudioTime');
|
| if (timeEl) timeEl.textContent = '00:00';
|
| const fill = document.getElementById('heatmapAudioProgressFill');
|
| if (fill) fill.style.width = '0%';
|
| }
|
|
|
| function playRadarNarration() {
|
| if (radarAudio && radarAudio.src) {
|
| radarAudio.play().catch(e => {
|
| console.warn('Impossible de lire le fichier audio radar:', e);
|
| const statusEl = document.getElementById('radarAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Fichier non trouvé';
|
| });
|
| } else {
|
| const statusEl = document.getElementById('radarAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Aucun fichier';
|
| }
|
| }
|
|
|
| function pauseRadarNarration() {
|
| if (radarAudio) radarAudio.pause();
|
| }
|
|
|
| function stopRadarNarration() {
|
| if (radarAudio) {
|
| radarAudio.pause();
|
| radarAudio.currentTime = 0;
|
| const fill = document.getElementById('radarAudioProgressFill');
|
| if (fill) fill.style.width = '0%';
|
| const statusEl = document.getElementById('radarAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Arrêté';
|
| }
|
| }
|
|
|
| function playHeatmapNarration() {
|
| if (heatmapAudio && heatmapAudio.src) {
|
| heatmapAudio.play().catch(e => {
|
| console.warn('Impossible de lire le fichier audio heatmap:', e);
|
| const statusEl = document.getElementById('heatmapAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Fichier non trouvé';
|
| });
|
| } else {
|
| const statusEl = document.getElementById('heatmapAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Aucun fichier';
|
| }
|
| }
|
|
|
| function pauseHeatmapNarration() {
|
| if (heatmapAudio) heatmapAudio.pause();
|
| }
|
|
|
| function stopHeatmapNarration() {
|
| if (heatmapAudio) {
|
| heatmapAudio.pause();
|
| heatmapAudio.currentTime = 0;
|
| const fill = document.getElementById('heatmapAudioProgressFill');
|
| if (fill) fill.style.width = '0%';
|
| const statusEl = document.getElementById('heatmapAudioStatus');
|
| if (statusEl) statusEl.textContent = 'Arrêté';
|
| }
|
| }
|
|
|
|
|
| document.addEventListener("DOMContentLoaded", () => {
|
| console.log("✅ DOM chargé, initialisation...");
|
| initAudioElements();
|
| loadScenarios();
|
| initTrustStars();
|
| initTrustSave();
|
| initTabs();
|
| initGDPR();
|
|
|
| updateTrustBar();
|
|
|
| document.getElementById("prevScenario").onclick = () => loadScenario(currentScenarioIndex - 1);
|
| document.getElementById("nextScenario").onclick = () => loadScenario(currentScenarioIndex + 1);
|
| document.getElementById("crossReadersBtn").onclick = navigateToCrossReading;
|
| });
|
|
|
|
|
| function initTabs() {
|
| const tabBtns = document.querySelectorAll('.tab-btn');
|
| const tabContents = document.querySelectorAll('.tab-content');
|
|
|
| tabBtns.forEach(btn => {
|
| btn.addEventListener('click', () => {
|
| const tabId = btn.getAttribute('data-tab');
|
|
|
| tabBtns.forEach(b => b.classList.remove('active'));
|
| tabContents.forEach(c => c.classList.remove('active'));
|
|
|
| btn.classList.add('active');
|
| document.getElementById(tabId).classList.add('active');
|
| });
|
| });
|
| }
|
|
|
|
|
| function initGDPR() {
|
| const gdprAccept = document.getElementById('gdprAccept');
|
| const gdprDecline = document.getElementById('gdprDecline');
|
| const evaluatorFields = document.getElementById('evaluatorFields');
|
| const anonymousMessage = document.getElementById('anonymousMessage');
|
|
|
| function updateGDPRFields() {
|
| if (gdprAccept.checked) {
|
| evaluatorFields.style.display = 'block';
|
| anonymousMessage.style.display = 'none';
|
|
|
| document.getElementById('evaluatorName').disabled = false;
|
| document.getElementById('evaluatorEmail').disabled = false;
|
| document.getElementById('evaluatorRole').disabled = false;
|
| document.getElementById('expertiseLevel').disabled = false;
|
| document.getElementById('messageMastery').disabled = false;
|
| } else if (gdprDecline.checked) {
|
| evaluatorFields.style.display = 'none';
|
| anonymousMessage.style.display = 'block';
|
|
|
| document.getElementById('evaluatorName').disabled = true;
|
| document.getElementById('evaluatorName').value = '';
|
| document.getElementById('evaluatorEmail').disabled = true;
|
| document.getElementById('evaluatorEmail').value = '';
|
| document.getElementById('evaluatorRole').disabled = true;
|
| document.getElementById('evaluatorRole').value = '';
|
| document.getElementById('expertiseLevel').disabled = true;
|
| document.getElementById('expertiseLevel').value = '';
|
| document.getElementById('messageMastery').disabled = true;
|
| document.getElementById('messageMastery').value = '';
|
| }
|
| }
|
|
|
| if (gdprAccept && gdprDecline) {
|
| gdprAccept.addEventListener('change', updateGDPRFields);
|
| gdprDecline.addEventListener('change', updateGDPRFields);
|
|
|
| updateGDPRFields();
|
| }
|
| }
|
|
|
|
|
| function loadScenarios() {
|
| console.log("Chargement des scénarios...");
|
| const possiblePaths = [
|
| "/static/scenarios.json",
|
| "scenarios.json",
|
| "./scenarios.json",
|
| "../scenarios.json"
|
| ];
|
|
|
| let loadAttempts = 0;
|
|
|
| function tryLoad(pathIndex) {
|
| if (pathIndex >= possiblePaths.length) {
|
| console.error("❌ Impossible de charger les scénarios depuis aucun chemin");
|
| console.log("Utilisation des scénarios par défaut (16 profils)");
|
| scenarios = generateDefaultScenarios();
|
|
|
| if (scenarios.length === 0) {
|
| showError("Impossible de charger les scénarios.");
|
| return;
|
| }
|
|
|
| loadScenario(0);
|
| return;
|
| }
|
|
|
| const path = possiblePaths[pathIndex];
|
| console.log(`Tentative de chargement depuis: ${path}`);
|
|
|
| fetch(path)
|
| .then(r => {
|
| if (!r.ok) throw new Error(`Erreur HTTP ${r.status}`);
|
| return r.json();
|
| })
|
| .then(data => {
|
| console.log("✅ Scénarios chargés:", data.scenarios?.length || 0);
|
| scenarios = data.scenarios || generateDefaultScenarios();
|
|
|
| if (scenarios.length === 0) {
|
| console.warn("Aucun scénario trouvé dans le fichier");
|
| scenarios = generateDefaultScenarios();
|
| }
|
|
|
| loadScenario(0);
|
| })
|
| .catch(error => {
|
| console.warn(`Échec pour ${path}:`, error.message);
|
| loadAttempts++;
|
| tryLoad(pathIndex + 1);
|
| });
|
| }
|
|
|
| tryLoad(0);
|
| }
|
|
|
| function generateDefaultScenarios() {
|
| console.log("Génération des 16 scénarios par défaut");
|
|
|
| const defaultScenarios = [...DEFAULT_SCENARIOS];
|
|
|
| defaultScenarios.forEach((scenario, index) => {
|
| scenario.competences = generateRandomCompetences(14);
|
| scenario.radar = generateProfileRadarData(scenario.title);
|
| scenario.reflAgent = generateReflAgentMessage(scenario.title);
|
| scenario.risk = calculateRiskLevel(scenario.title);
|
| });
|
|
|
| return defaultScenarios;
|
| }
|
|
|
| function generateRandomCompetences(count) {
|
| const competenceLabels = [
|
| "Analyse de texte", "Rédaction académique", "Recherche documentaire",
|
| "Présentation orale", "Travail collaboratif", "Gestion du temps",
|
| "Résolution de problèmes", "Pensée critique", "Communication écrite",
|
| "Organisation personnelle", "Auto-évaluation", "Utilisation des TICE",
|
| "Métacognition", "Adaptabilité"
|
| ];
|
|
|
| const competences = [];
|
| for (let i = 0; i < count; i++) {
|
| const labelIndex = i % competenceLabels.length;
|
| const value = 30 + Math.floor(Math.random() * 65);
|
| competences.push({
|
| label: competenceLabels[labelIndex],
|
| value: value
|
| });
|
| }
|
|
|
| return competences;
|
| }
|
|
|
| function generateProfileRadarData(profileTitle) {
|
| let baseValues;
|
|
|
| switch(profileTitle) {
|
| case "Étudiant engagé":
|
| baseValues = [85, 72, 68, 35, 74, 80, 78];
|
| break;
|
| case "Étudiant actif mais inefficace":
|
| baseValues = [90, 65, 60, 60, 70, 85, 65];
|
| break;
|
| case "Étudiant orienté vers le succès":
|
| baseValues = [90, 85, 80, 25, 90, 75, 85];
|
| break;
|
| case "Étudiant motivé":
|
| baseValues = [65, 70, 65, 45, 60, 70, 68];
|
| break;
|
| case "Étudiant surmotivé":
|
| baseValues = [95, 80, 75, 20, 88, 98, 82];
|
| break;
|
| case "Étudiant stratégique":
|
| baseValues = [70, 78, 72, 40, 75, 55, 80];
|
| break;
|
| case "Étudiant en amélioration":
|
| baseValues = [70, 68, 65, 50, 68, 72, 70];
|
| break;
|
| case "Étudiant en difficulté":
|
| baseValues = [72, 60, 55, 70, 65, 85, 58];
|
| break;
|
| case "Étudiant évitant l'échec":
|
| baseValues = [35, 40, 38, 80, 30, 45, 40];
|
| break;
|
| case "Étudiant à risque":
|
| baseValues = [75, 60, 55, 65, 55, 70, 58];
|
| break;
|
| case "Étudiant en progression":
|
| baseValues = [70, 78, 75, 45, 68, 65, 78];
|
| break;
|
| case "Étudiant acceptant l'échec":
|
| baseValues = [85, 70, 68, 55, 58, 62, 72];
|
| break;
|
| case "Étudiant inactif":
|
| baseValues = [15, 20, 18, 90, 10, 25, 22];
|
| break;
|
| case "Étudiant non engagé":
|
| baseValues = [30, 35, 32, 75, 25, 40, 38];
|
| break;
|
| case "Étudiant persévérant":
|
| baseValues = [55, 65, 64, 68, 58, 60, 66];
|
| break;
|
| case "Étudiant actif":
|
| baseValues = [85, 62, 60, 58, 45, 75, 63];
|
| break;
|
| default:
|
| baseValues = [70, 65, 62, 50, 65, 70, 68];
|
| }
|
|
|
| return DEFAULT_RADAR_METRICS.map((metric, index) => ({
|
| label: metric.label,
|
| value: Math.max(10, Math.min(100, baseValues[index] + (Math.random() * 10 - 5)))
|
| }));
|
| }
|
|
|
| function generateReflAgentMessage(profileTitle) {
|
| const messages = {
|
| "Étudiant engagé": "Félicitations ! Ton engagement est remarquable. Continue sur cette lancée en maintenant ta régularité de travail.",
|
| "Étudiant actif mais inefficace": "Tu travailles beaucoup, mais l'efficacité pourrait être améliorée. Concentre-toi sur la qualité plutôt que la quantité.",
|
| "Étudiant orienté vers le succès": "Ton orientation vers la réussite est excellente. N'oublie pas que l'apprentissage est aussi important que les résultats.",
|
| "Étudiant motivé": "Ta motivation est un atout précieux. Structure ton travail pour transformer cette motivation en résultats concrets.",
|
| "Étudiant surmotivé": "Attention au surinvestissement. Un équilibre est nécessaire pour éviter l'épuisement. Priorise les activités essentielles.",
|
| "Étudiant stratégique": "Ton approche stratégique est intelligente. Assure-toi de ne pas négliger les compétences transversales importantes.",
|
| "Étudiant en amélioration": "Tes progrès sont visibles ! Continue à travailler régulièrement pour consolider ces améliorations.",
|
| "Étudiant en difficulté": "Tu rencontres des difficultés, mais ne baisse pas les bras. Demande de l'aide et concentre-toi sur les bases.",
|
| "Étudiant évitant l'échec": "La peur de l'échec peut être paralysante. Rappelle-toi que l'erreur fait partie de l'apprentissage.",
|
| "Étudiant à risque": "Ton engagement est fragile. Commence par de petits objectifs réalisables pour reprendre confiance.",
|
| "Étudiant en progression": "Tes compétences techniques s'améliorent bien. Maintenant, travaille sur leur application dans des contextes variés.",
|
| "Étudiant acceptant l'échec": "Ton attitude face à l'échec est constructive. Utilise ces expériences pour identifier tes points d'amélioration.",
|
| "Étudiant inactif": "Le premier pas est le plus difficile. Choisis une seule activité simple pour commencer, sans pression.",
|
| "Étudiant non engagé": "Il est normal de manquer d'intérêt parfois. Cherche un aspect du cours qui pourrait te motiver davantage.",
|
| "Étudiant persévérant": "Tes compétences sont solides. Fais confiance à ton potentiel et ose t'investir pleinement.",
|
| "Étudiant actif": "Ton engagement est fort mais attention à ne pas t'épuiser. Apprends à mieux doser tes efforts."
|
| };
|
|
|
| return messages[profileTitle] || "Analyse de votre profil d'apprentissage en cours...";
|
| }
|
|
|
| function calculateRiskLevel(profileTitle) {
|
| const riskLevels = {
|
| "Étudiant engagé": 20,
|
| "Étudiant actif mais inefficace": 50,
|
| "Étudiant orienté vers le succès": 25,
|
| "Étudiant motivé": 30,
|
| "Étudiant surmotivé": 40,
|
| "Étudiant stratégique": 35,
|
| "Étudiant en amélioration": 45,
|
| "Étudiant en difficulté": 70,
|
| "Étudiant évitant l'échec": 65,
|
| "Étudiant à risque": 85,
|
| "Étudiant en progression": 40,
|
| "Étudiant acceptant l'échec": 55,
|
| "Étudiant inactif": 90,
|
| "Étudiant non engagé": 75,
|
| "Étudiant persévérant": 45,
|
| "Étudiant actif": 60
|
| };
|
|
|
| return riskLevels[profileTitle] || 50;
|
| }
|
|
|
| function showError(message) {
|
| const manifestList = document.getElementById("manifest-list");
|
| if (manifestList) {
|
| manifestList.innerHTML =
|
| `<div class="manifest-item" style="background:#FFEBEE;color:#C62828;">
|
| ${message}<br>
|
| <small>Veuillez vérifier que le fichier scenarios.json est présent.</small>
|
| </div>`;
|
| }
|
|
|
| console.error(message);
|
|
|
| document.getElementById("prevScenario").disabled = true;
|
| document.getElementById("nextScenario").disabled = true;
|
| }
|
|
|
|
|
| function loadScenario(index) {
|
| console.log("Chargement scénario", index);
|
| if (!scenarios || scenarios.length === 0) {
|
| console.error("Aucun scénario disponible");
|
| return;
|
| }
|
|
|
| if (index < 0 || index >= scenarios.length) {
|
| console.warn(`Index ${index} hors limites (0-${scenarios.length-1})`);
|
| return;
|
| }
|
|
|
| currentScenarioIndex = index;
|
| const s = scenarios[index];
|
|
|
| const titleElement = document.getElementById("scenarioTitle");
|
| if (titleElement) {
|
| titleElement.textContent = `Scénario ${s.id} – ${s.title}`;
|
| }
|
|
|
| const manifestList = document.getElementById("manifest-list");
|
| if (manifestList) {
|
| manifestList.innerHTML = `
|
| <div class="manifest-item">
|
| <b>Type de Manifest :</b> ${s.manifest?.type || "Non spécifié"}<br>
|
| <b>Manifeste (écrit par l'étudiant) :</b> ${s.manifest?.manifeste || "Non disponible"}<br>
|
| <b>Description du Profil :</b> ${s.manifest?.description || "Non disponible"}
|
| </div>`;
|
| }
|
|
|
| if (s.competences) {
|
| updateCompactCompetences(s.competences);
|
| }
|
|
|
| if (s.radar && s.radar.length > 0) {
|
| radarMetrics = s.radar.filter(metric => metric.label !== "Engagement global");
|
| } else {
|
| radarMetrics = DEFAULT_RADAR_METRICS.map(metric => {
|
| const variation = (index % 7) * 5 - 15;
|
| const newValue = Math.max(10, Math.min(95, metric.value + variation));
|
| return {
|
| label: metric.label,
|
| value: newValue
|
| };
|
| });
|
| }
|
|
|
| updateCompactRadarMetricsGrid();
|
| drawRadar();
|
| updateCompactRadarBotMessage(s);
|
| drawCompactEnrichedHeatmapWithAxes(s);
|
|
|
| const modeSelect = document.getElementById("persistenceMode");
|
| if (modeSelect) {
|
| modeSelect.value = "combined";
|
| updatePersistenceIndicators("combined");
|
| }
|
|
|
| updatePerseveranceProfile(s.title);
|
|
|
| const reflagentElement = document.getElementById("reflagent");
|
| if (reflagentElement) {
|
| reflagentElement.textContent = s.reflAgent || "Message d'analyse non disponible pour ce scénario.";
|
| }
|
|
|
| updateNavButtons();
|
| updateStats(s);
|
| resetTrustEvaluation();
|
|
|
| loadRadarAudioForScenario(s.id);
|
| loadHeatmapAudioForScenario(s.id);
|
| }
|
|
|
|
|
|
|
| function updateCompactCompetences(competences) {
|
| const container = document.getElementById("compact-competences");
|
| if (!container) return;
|
|
|
| container.innerHTML = '';
|
|
|
| if (!competences || competences.length === 0) {
|
| container.innerHTML = '<em>Aucune donnée de compétence disponible</em>';
|
| return;
|
| }
|
|
|
| const gridContainer = document.createElement('div');
|
| gridContainer.className = 'compact-competences-grid';
|
|
|
| const maxCompetences = 14;
|
| const displayedCompetences = competences.slice(0, maxCompetences);
|
|
|
| displayedCompetences.forEach(comp => {
|
| let color, colorClass;
|
| if (comp.value < 50) {
|
| color = '#E53935';
|
| colorClass = 'low';
|
| } else if (comp.value < 70) {
|
| color = '#FB8C00';
|
| colorClass = 'medium';
|
| } else {
|
| color = '#43A047';
|
| colorClass = 'high';
|
| }
|
|
|
| const compItem = document.createElement('div');
|
| compItem.className = 'compact-competence-matrix-item';
|
| compItem.innerHTML = `
|
| <div class="compact-matrix-competence-label">
|
| ${comp.label}
|
| </div>
|
| <div class="compact-matrix-competence-value ${colorClass}">
|
| ${comp.value}%
|
| </div>
|
| <div class="compact-matrix-competence-bar">
|
| <div class="compact-matrix-competence-fill" style="width: ${comp.value}%; background: ${color};">
|
| </div>
|
| </div>
|
| <div>
|
| <span>0%</span>
|
| <span>100%</span>
|
| </div>
|
| `;
|
|
|
| gridContainer.appendChild(compItem);
|
| });
|
|
|
| const emptySlots = maxCompetences - displayedCompetences.length;
|
| for (let i = 0; i < emptySlots; i++) {
|
| const emptyItem = document.createElement('div');
|
| emptyItem.className = 'compact-competence-matrix-item';
|
| emptyItem.style.opacity = '0.3';
|
| emptyItem.innerHTML = `
|
| <div class="compact-matrix-competence-label" style="color: #999;">
|
| Compétence non définie
|
| </div>
|
| <div class="compact-matrix-competence-value" style="color: #999;">
|
| --
|
| </div>
|
| <div class="compact-matrix-competence-bar">
|
| <div class="compact-matrix-competence-fill" style="width: 0%; background: #999;">
|
| </div>
|
| </div>
|
| <div>
|
| <span>0%</span>
|
| <span>100%</span>
|
| </div>
|
| `;
|
| gridContainer.appendChild(emptyItem);
|
| }
|
|
|
| container.appendChild(gridContainer);
|
| }
|
|
|
| function updateCompactRadarMetricsGrid() {
|
| const grid = document.getElementById("compact-radar-metrics-grid");
|
| if (!grid) return;
|
|
|
| grid.innerHTML = '';
|
|
|
| if (!radarMetrics || radarMetrics.length === 0) {
|
| grid.innerHTML = '<em>Aucune métrique radar disponible</em>';
|
| return;
|
| }
|
|
|
| radarMetrics.forEach(metric => {
|
| let colorClass = "";
|
| if (metric.value >= 70) colorClass = "high";
|
| else if (metric.value >= 40) colorClass = "medium";
|
| else colorClass = "low";
|
|
|
| let icon = "📊";
|
| if (metric.label.includes("Démarrage")) icon = "🚀";
|
| else if (metric.label.includes("Éléments des connaissances validées")) icon = "🎓";
|
| else if (metric.label.includes("Niveau moyen")) icon = "📈";
|
| else if (metric.label.includes("Taux d'erreur")) icon = "🎯";
|
| else if (metric.label.includes("Achèvement")) icon = "🏁";
|
| else if (metric.label.includes("Interactions")) icon = "📚";
|
| else if (metric.label.includes("Score")) icon = "🔧";
|
|
|
| let description = "";
|
| if (metric.label.includes("Démarrage")) description = "Rapidité d'initiation de l'activité d'apprentissage";
|
| else if (metric.label.includes("Éléments des connaissances validées")) description = "Taux de validation des skills";
|
| else if (metric.label.includes("Niveau moyen")) description = "Degré de maîtrise des compétences";
|
| else if (metric.label.includes("Taux d'erreur")) description = "Précision et attention";
|
| else if (metric.label.includes("Achèvement")) description = "Terminaison des tâches";
|
| else if (metric.label.includes("Interactions")) description = "Usage des micro-ressources (vidéos)";
|
| else if (metric.label.includes("Score")) description = "Degré d'activité et d'implication";
|
|
|
| const metricCard = document.createElement("div");
|
| metricCard.className = "compact-metric-card";
|
| metricCard.innerHTML = `
|
| <div class="compact-metric-icon">${icon}</div>
|
| <div class="compact-metric-name">${metric.label}</div>
|
| <div class="compact-metric-value ${colorClass}">${metric.value}%</div>
|
| <div class="compact-metric-description">${description}</div>
|
| `;
|
|
|
| grid.appendChild(metricCard);
|
| });
|
| }
|
|
|
| function updateCompactRadarBotMessage(scenario) {
|
| const radarBotContent = document.getElementById("compact-radar-bot-content");
|
| const radarBotInsights = document.getElementById("compact-radar-bot-insights");
|
|
|
| if (!radarBotContent || !radarBotInsights) return;
|
|
|
| const profileMessage = profileMessages[scenario.title] || {
|
| title: "Profil d'Apprentissage",
|
| message: "Analyse de votre profil d'apprentissage en cours...",
|
| insights: [
|
| { icon: "📊", text: "Évaluation indicateurs" },
|
| { icon: "🎯", text: "Forces et améliorations" },
|
| { icon: "🚀", text: "Recommandations" }
|
| ]
|
| };
|
|
|
| radarBotContent.innerHTML = `<strong>${profileMessage.title}</strong><br>${profileMessage.message}`;
|
|
|
| radarBotInsights.innerHTML = '';
|
| profileMessage.insights.forEach(insight => {
|
| const insightElement = document.createElement('div');
|
| insightElement.className = 'compact-radar-insight-item';
|
| insightElement.innerHTML = `
|
| <div class="radar-insight-icon">${insight.icon}</div>
|
| <div class="radar-insight-text">${insight.text}</div>
|
| `;
|
| radarBotInsights.appendChild(insightElement);
|
| });
|
| }
|
|
|
| function drawCompactEnrichedHeatmapWithAxes(scenario) {
|
| const canvas = document.getElementById("heatmap");
|
| if (!canvas) return;
|
|
|
| const ctx = canvas.getContext("2d");
|
| const cellSize = 15;
|
| const padding = 1;
|
| const days = ["L", "M", "M", "J", "V", "S", "D"];
|
| const weeks = 4;
|
| const totalDays = weeks * 7;
|
|
|
| ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
| const scenarioTitles = {
|
| 1: { title: "Engagé mais désorganisé", emoji: "😅", pattern: "Effort concentré avant échéances" },
|
| 2: { title: "Actif mais peu efficace", emoji: "😰", pattern: "Démarrage lent, accélération tardive" },
|
| 3: { title: "Autonome et stratégique", emoji: "😊", pattern: "Travail régulier et équilibré" },
|
| 4: { title: "Motivé et constant", emoji: "👍", pattern: "Rythme régulier toute la semaine" },
|
| 5: { title: "Surinvestissement", emoji: "🔥", pattern: "Activité intense, risque de surcharge" },
|
| 6: { title: "Stratégique et ciblé", emoji: "🎯", pattern: "Efforts concentrés sur les priorités" },
|
| 7: { title: "Amélioration continue", emoji: "📈", pattern: "Progression visible semaine après semaine" },
|
| 8: { title: "Difficultés persistantes", emoji: "😔", pattern: "Efforts dispersés, peu de régularité" },
|
| 9: { title: "Évitement", emoji: "😨", pattern: "Activité minimale, pics sporadiques" },
|
| 10: { title: "Risque d'abandon", emoji: "⚠️", pattern: "Très faible activité, irrégularité totale" },
|
| 11: { title: "Progression technique", emoji: "🔧", pattern: "Amélioration régulière des compétences" },
|
| 12: { title: "Résilience", emoji: "💪", pattern: "Persévérance malgré les difficultés" },
|
| 13: { title: "Inactivité", emoji: "😴", pattern: "Très peu d'activité détectée" },
|
| 14: { title: "Désengagement", emoji: "😑", pattern: "Activité sporadique et décroissante" },
|
| 15: { title: "Persévérant malgré le doute", emoji: "🌱", pattern: "Accélération progressive en fin de semaine" },
|
| 16: { title: "Actif mais à risque d'épuisement", emoji: "⚡", pattern: "Forte activité en début de semaine" }
|
| };
|
|
|
| const scenarioInfo = scenarioTitles[scenario.id] || { title: "Votre activité", emoji: "📊", pattern: "Schéma à analyser" };
|
|
|
| ctx.font = "bold 14px Arial";
|
| ctx.fillStyle = "#1976D2";
|
| ctx.textAlign = "center";
|
| ctx.fillText(`${scenarioInfo.emoji} ${scenarioInfo.title}`, canvas.width / 2, 25);
|
|
|
| ctx.font = "12px Arial";
|
| ctx.fillStyle = "#666";
|
| ctx.fillText(`${scenarioInfo.pattern}`, canvas.width / 2, 45);
|
|
|
| const activityData = generateCompactPersistenceData(scenario.id, totalDays);
|
|
|
| const colors = ["#EBEDF0", "#C6E48B", "#7BC96F", "#239A3B", "#196127"];
|
|
|
| const startX = 60;
|
| const startY = 80;
|
|
|
| ctx.font = "11px Arial";
|
| ctx.fillStyle = "#555";
|
| ctx.textAlign = "right";
|
| ctx.textBaseline = "middle";
|
|
|
| for (let weekday = 0; weekday < 7; weekday++) {
|
| const y = startY + weekday * (cellSize + padding) + cellSize / 2;
|
| ctx.fillText(days[weekday], startX - 10, y);
|
| }
|
|
|
| ctx.font = "11px Arial";
|
| ctx.fillStyle = "#555";
|
| ctx.textAlign = "center";
|
| ctx.textBaseline = "bottom";
|
|
|
| for (let week = 0; week < weeks; week++) {
|
| const x = startX + week * (cellSize * 7 + padding * 7) + (cellSize * 7) / 2;
|
| ctx.fillText(`S${week + 1}`, x, startY - 5);
|
| }
|
|
|
| ctx.font = "10px Arial";
|
| ctx.fillStyle = "#777";
|
| ctx.textAlign = "center";
|
| ctx.fillText("Semaines", canvas.width / 2, startY - 15);
|
|
|
| ctx.save();
|
| ctx.translate(startX - 25, startY + (cellSize * 7) / 2);
|
| ctx.rotate(-Math.PI / 2);
|
| ctx.fillText("Jours", 0, 0);
|
| ctx.restore();
|
|
|
| for (let day = 0; day < totalDays; day++) {
|
| const week = Math.floor(day / 7);
|
| const weekday = day % 7;
|
|
|
| const x = startX + week * (cellSize * 7 + padding * 7) + weekday * (cellSize + padding);
|
| const y = startY + weekday * (cellSize + padding);
|
|
|
| const intensity = activityData[day];
|
|
|
| ctx.fillStyle = colors[intensity];
|
| ctx.fillRect(x, y, cellSize, cellSize);
|
|
|
| if (weekday === 4) {
|
| ctx.strokeStyle = "#FF6B6B";
|
| ctx.lineWidth = 1.5;
|
| } else {
|
| ctx.strokeStyle = intensity > 0 ? "#239A3B" : "#eee";
|
| ctx.lineWidth = 0.5;
|
| }
|
| ctx.strokeRect(x, y, cellSize, cellSize);
|
| }
|
|
|
| analyzeCompactPersistenceMetrics(activityData, scenario.id);
|
|
|
| const currentMode = document.getElementById("persistenceMode").value;
|
| updatePersistenceIndicators(currentMode);
|
| }
|
|
|
| function updatePersistenceIndicators(mode) {
|
| const regularityIndicator = document.getElementById("regularity-indicator");
|
| const regularityDesc = document.getElementById("regularity-description");
|
| const deadlineIndicator = document.getElementById("deadline-indicator");
|
| const deadlineDesc = document.getElementById("deadline-description");
|
| const effortIndicator = document.getElementById("effort-indicator");
|
| const effortDesc = document.getElementById("effort-description");
|
|
|
| const regularityText = document.getElementById("compact-regularityText");
|
|
|
| if (!regularityIndicator || !deadlineIndicator || !effortIndicator) return;
|
|
|
| regularityIndicator.style.display = "none";
|
| regularityDesc.style.display = "none";
|
| deadlineIndicator.style.display = "none";
|
| deadlineDesc.style.display = "none";
|
| effortIndicator.style.display = "none";
|
| effortDesc.style.display = "none";
|
|
|
| const currentScenario = scenarios[currentScenarioIndex];
|
| if (!currentScenario) return;
|
|
|
| const profile = perseveranceProfiles[currentScenario.title];
|
|
|
| switch(mode) {
|
| case "regularity":
|
| regularityIndicator.style.display = "flex";
|
| regularityDesc.style.display = "block";
|
| if (regularityText) {
|
| regularityText.innerHTML = `
|
| <div style="font-size: 12px; color: #555; line-height: 1.4;">
|
| <strong>Analyse de la régularité du travail</strong><br>
|
| ${profile ? profile.interpretation : "La constance de l'activité de l'apprenant dans le temps."}
|
| </div>
|
| `;
|
| }
|
| break;
|
| case "deadline":
|
| deadlineIndicator.style.display = "flex";
|
| deadlineDesc.style.display = "block";
|
| if (regularityText) {
|
| regularityText.innerHTML = `
|
| <div style="font-size: 12px; color: #555; line-height: 1.4;">
|
| <strong>Analyse de la gestion des échéances</strong><br>
|
| Capacité à respecter les délais et à organiser le travail avant les dates limites.
|
| </div>
|
| `;
|
| }
|
| break;
|
| case "effortPattern":
|
| effortIndicator.style.display = "flex";
|
| effortDesc.style.display = "block";
|
| if (regularityText) {
|
| regularityText.innerHTML = `
|
| <div style="font-size: 12px; color: #555; line-height: 1.4;">
|
| <strong>Analyse du schéma d'effort</strong><br>
|
| La dynamique temporelle de l'effort et la distribution de l'activité.
|
| </div>
|
| `;
|
| }
|
| break;
|
| case "combined":
|
| regularityIndicator.style.display = "flex";
|
| regularityDesc.style.display = "block";
|
| deadlineIndicator.style.display = "flex";
|
| deadlineDesc.style.display = "block";
|
| effortIndicator.style.display = "flex";
|
| effortDesc.style.display = "block";
|
| if (regularityText) {
|
| regularityText.innerHTML = `
|
| <div style="font-size: 12px; color: #555; line-height: 1.4;">
|
| <strong>Vue combinée</strong><br>
|
| ${profile ? profile.interpretation : "Analyse complète de la persévérance et de la gestion des efforts."}
|
| </div>
|
| `;
|
| }
|
| break;
|
| default:
|
| regularityIndicator.style.display = "flex";
|
| regularityDesc.style.display = "block";
|
| deadlineIndicator.style.display = "flex";
|
| deadlineDesc.style.display = "block";
|
| effortIndicator.style.display = "flex";
|
| effortDesc.style.display = "block";
|
| }
|
| }
|
|
|
| function updatePerseveranceProfile(scenarioTitle) {
|
| const profile = perseveranceProfiles[scenarioTitle];
|
|
|
| const regularityScore = document.getElementById("compact-regularityScore");
|
| const deadlineScore = document.getElementById("compact-deadlineScore");
|
| const effortPattern = document.getElementById("compact-effortPattern");
|
| const regularityText = document.getElementById("compact-regularityText");
|
|
|
| if (!profile) {
|
| if (regularityText) {
|
| regularityText.innerHTML = `
|
| <div style="font-size: 12px; color: #555; line-height: 1.4;">
|
| Analyse de persévérance non disponible pour ce profil.
|
| </div>
|
| `;
|
| }
|
| return;
|
| }
|
|
|
| if (regularityScore) {
|
| regularityScore.textContent = profile.regularity + "%";
|
| regularityScore.style.color = profile.color;
|
| }
|
|
|
| if (deadlineScore) {
|
| deadlineScore.textContent = profile.deadline + "%";
|
| deadlineScore.style.color = profile.color;
|
| }
|
|
|
| if (effortPattern) {
|
| effortPattern.textContent = profile.effortPattern;
|
| effortPattern.style.color = profile.color;
|
| }
|
|
|
| if (regularityText) {
|
| regularityText.innerHTML = `
|
| <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 5px;">
|
| <div style="width: 12px; height: 12px; border-radius: 50%; background: ${profile.color};"></div>
|
| <strong style="color: ${profile.color};">${profile.level}</strong>
|
| </div>
|
| <div style="font-size: 12px; color: #555; line-height: 1.4;">
|
| ${profile.interpretation}
|
| </div>
|
| `;
|
| }
|
| }
|
|
|
| function generateCompactPersistenceData(scenarioId, totalDays) {
|
| const data = new Array(totalDays).fill(0);
|
|
|
| const profile = Object.values(perseveranceProfiles)[scenarioId - 1] || perseveranceProfiles["Étudiant engagé"];
|
|
|
| for (let i = 0; i < totalDays; i++) {
|
| const weekday = i % 7;
|
| const week = Math.floor(i / 7);
|
| const progress = i / totalDays;
|
|
|
| if (profile.effortPattern.includes("Pic d'activité jeudi/vendredi")) {
|
| if (weekday === 3 || weekday === 4) {
|
| data[i] = 4;
|
| } else if (weekday === 5 || weekday === 6) {
|
| data[i] = 1;
|
| } else {
|
| data[i] = 2;
|
| }
|
| } else if (profile.effortPattern.includes("Travail weekend")) {
|
| if (weekday === 5 || weekday === 6) {
|
| data[i] = 4;
|
| } else {
|
| data[i] = 2;
|
| }
|
| } else if (profile.effortPattern.includes("Accélération progressive")) {
|
| data[i] = Math.min(4, Math.floor(progress * 4) + 1);
|
| } else if (profile.effortPattern.includes("Activité minimale")) {
|
| if (week === 0) {
|
| data[i] = Math.random() > 0.7 ? 1 : 0;
|
| } else {
|
| data[i] = Math.random() > 0.8 ? 1 : 0;
|
| }
|
| } else {
|
| if (weekday === 5 || weekday === 6) {
|
| data[i] = 2;
|
| } else {
|
| data[i] = 3;
|
| }
|
| }
|
| }
|
|
|
| return data;
|
| }
|
|
|
| function analyzeCompactPersistenceMetrics(activityData, scenarioId) {
|
|
|
| }
|
|
|
|
|
| function drawRadar() {
|
| const canvas = document.getElementById("radar");
|
| if (!canvas) {
|
| console.error("Canvas radar non trouvé!");
|
| return;
|
| }
|
|
|
| const ctx = canvas.getContext("2d");
|
| const cx = canvas.width / 2;
|
| const cy = canvas.height / 2;
|
| const radius = Math.min(cx, cy) - 40;
|
| const n = radarMetrics.length;
|
|
|
| ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
| for (let i = 1; i <= 5; i++) {
|
| ctx.beginPath();
|
| ctx.arc(cx, cy, (radius / 5) * i, 0, 2 * Math.PI);
|
| ctx.strokeStyle = "#e0e0e0";
|
| ctx.stroke();
|
|
|
| if (i % 2 === 0 || i === 1 || i === 5) {
|
| const percent = (i * 20) + "%";
|
| ctx.save();
|
| ctx.font = "10px Arial";
|
| ctx.fillStyle = "#666";
|
| ctx.textAlign = "center";
|
| ctx.textBaseline = "middle";
|
| ctx.fillText(percent, cx, cy - (radius / 5) * i - 5);
|
| ctx.restore();
|
| }
|
| }
|
|
|
| radarMetrics.forEach((m, i) => {
|
| const angle = (2 * Math.PI * i) / n - Math.PI / 2;
|
|
|
| ctx.beginPath();
|
| ctx.moveTo(cx, cy);
|
| ctx.lineTo(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle));
|
| ctx.strokeStyle = "#b0bec5";
|
| ctx.stroke();
|
|
|
| const tx = cx + (radius + 25) * Math.cos(angle);
|
| const ty = cy + (radius + 25) * Math.sin(angle);
|
|
|
| ctx.font = "10px Arial";
|
| ctx.fillStyle = "#000";
|
| ctx.textAlign = angle > Math.PI / 2 || angle < -Math.PI / 2 ? "right" : "left";
|
| ctx.textBaseline = "middle";
|
|
|
| let label = m.label;
|
| if (label.length > 15) {
|
| label = label.substring(0, 12) + "...";
|
| }
|
| ctx.fillText(label, tx, ty);
|
| });
|
|
|
| ctx.beginPath();
|
| radarMetrics.forEach((m, i) => {
|
| const angle = (2 * Math.PI * i) / n - Math.PI / 2;
|
| const r = radius * (m.value / 100);
|
| const x = cx + r * Math.cos(angle);
|
| const y = cy + r * Math.sin(angle);
|
| i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
|
| });
|
| ctx.closePath();
|
|
|
| ctx.fillStyle = "rgba(25,118,210,0.25)";
|
| ctx.fill();
|
| ctx.strokeStyle = "#1976D2";
|
| ctx.lineWidth = 2;
|
| ctx.stroke();
|
|
|
| radarMetrics.forEach((m, i) => {
|
| const angle = (2 * Math.PI * i) / n - Math.PI / 2;
|
| const r = radius * (m.value / 100);
|
| const x = cx + r * Math.cos(angle);
|
| const y = cy + r * Math.sin(angle);
|
|
|
| ctx.beginPath();
|
| ctx.arc(x, y, 4, 0, 2 * Math.PI);
|
| ctx.fillStyle = "#1976D2";
|
| ctx.fill();
|
|
|
| ctx.save();
|
| ctx.font = "bold 11px Arial";
|
| ctx.fillStyle = "#1976D2";
|
| ctx.textAlign = "center";
|
| ctx.textBaseline = "middle";
|
|
|
| const labelOffset = 15;
|
| const labelX = x + labelOffset * Math.cos(angle);
|
| const labelY = y + labelOffset * Math.sin(angle);
|
|
|
| ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
|
| ctx.fillRect(labelX - 15, labelY - 8, 30, 16);
|
|
|
| ctx.fillStyle = "#1976D2";
|
| ctx.fillText(m.value + "%", labelX, labelY);
|
| ctx.restore();
|
| });
|
| }
|
|
|
|
|
| function updateNavButtons() {
|
| if (!scenarios || scenarios.length === 0) {
|
| document.getElementById("prevScenario").disabled = true;
|
| document.getElementById("nextScenario").disabled = true;
|
| return;
|
| }
|
|
|
| document.getElementById("prevScenario").disabled = currentScenarioIndex === 0;
|
| document.getElementById("nextScenario").disabled = currentScenarioIndex === scenarios.length - 1;
|
| }
|
|
|
|
|
| function navigateToCrossReading() {
|
| console.log('Navigation vers la page de lecture croisée...');
|
|
|
| const reflectionDiv = document.getElementById('reflection');
|
| if (reflectionDiv) {
|
| reflectionDiv.style.opacity = '0.7';
|
| reflectionDiv.style.transition = 'opacity 0.3s ease';
|
| }
|
|
|
| setTimeout(() => {
|
| const possiblePaths = [
|
| 'cross_reading/cross_readers.html',
|
| './cross_reading/cross_readers.html',
|
| '../cross_reading/cross_readers.html',
|
| 'cross_readers.html',
|
| './cross_readers.html'
|
| ];
|
|
|
| function tryRedirect(index) {
|
| if (index >= possiblePaths.length) {
|
| console.error('Page de lecture croisée introuvable');
|
| showNotification('Erreur', 'Page de lecture croisée introuvable', 'error');
|
|
|
| if (reflectionDiv) {
|
| reflectionDiv.style.opacity = '1';
|
| }
|
| return;
|
| }
|
|
|
| const path = possiblePaths[index];
|
|
|
| fetch(path, { method: 'HEAD' })
|
| .then(response => {
|
| if (response.ok) {
|
| window.location.href = path;
|
| } else {
|
| tryRedirect(index + 1);
|
| }
|
| })
|
| .catch(() => {
|
| tryRedirect(index + 1);
|
| });
|
| }
|
|
|
| tryRedirect(0);
|
| }, 300);
|
| }
|
|
|
|
|
| function initTrustStars(){
|
| console.log("Initialisation des étoiles...");
|
|
|
| for (const key in trustMetrics) {
|
| trustMetrics[key] = 0;
|
| }
|
|
|
| let starsCreated = 0;
|
|
|
| document.querySelectorAll(".stars").forEach(div => {
|
| const metric = div.dataset.metric;
|
| console.log(`Création des étoiles pour: ${metric}`);
|
|
|
| if (!trustMetrics.hasOwnProperty(metric)) {
|
| console.error(`Métrique inconnue: ${metric}`);
|
| return;
|
| }
|
|
|
| div.innerHTML = '';
|
|
|
| for (let i = 1; i <= 5; i++) {
|
| const star = document.createElement("span");
|
| star.textContent = "★";
|
| star.classList.add("inactive");
|
| star.style.cursor = "pointer";
|
| star.title = `${i} étoile${i > 1 ? 's' : ''}`;
|
|
|
| star.dataset.value = i;
|
| star.dataset.metric = metric;
|
|
|
| star.onclick = function() {
|
| const value = parseInt(this.dataset.value);
|
| const metric = this.dataset.metric;
|
| console.log(`Clic sur ${metric}: ${value} étoiles`);
|
|
|
| trustMetrics[metric] = value;
|
|
|
| const allStarsInGroup = this.parentElement.children;
|
| for (let j = 0; j < allStarsInGroup.length; j++) {
|
| const starElem = allStarsInGroup[j];
|
| const starValue = parseInt(starElem.dataset.value);
|
|
|
| if (starValue <= value) {
|
| starElem.classList.remove("inactive");
|
| starElem.classList.add("active");
|
| } else {
|
| starElem.classList.add("inactive");
|
| starElem.classList.remove("active");
|
| }
|
| }
|
|
|
| updateTrustBar();
|
| };
|
|
|
| div.appendChild(star);
|
| starsCreated++;
|
| }
|
| });
|
|
|
| console.log(`${starsCreated} étoiles créées pour ${Object.keys(trustMetrics).length} métriques`);
|
| console.log("Métriques initialisées:", trustMetrics);
|
| }
|
|
|
| function updateTrustBar(){
|
| console.log("=== MISE À JOUR BARRE DE CONFIANCE ===");
|
|
|
| let scoreTotal = 0;
|
| let scoreMaxPossible = 0;
|
| let details = [];
|
|
|
| for (const metric in trustMetrics) {
|
| const valeur = trustMetrics[metric];
|
| const poids = trustWeights[metric];
|
| const contribution = valeur * poids;
|
| const maxContribution = 5 * poids;
|
|
|
| scoreTotal += contribution;
|
| scoreMaxPossible += maxContribution;
|
|
|
| details.push({
|
| métrique: metric,
|
| valeur: valeur,
|
| poids: poids,
|
| contribution: contribution.toFixed(2),
|
| max: maxContribution.toFixed(2)
|
| });
|
| }
|
|
|
| console.log("Détails du calcul:");
|
| details.forEach(d => {
|
| console.log(`${d.métrique}: ${d.valeur}/5 × ${d.poids} = ${d.contribution} / ${d.max}`);
|
| });
|
|
|
| console.log(`Total: ${scoreTotal.toFixed(2)} / ${scoreMaxPossible.toFixed(2)}`);
|
|
|
| let pourcentage = 0;
|
| if (scoreMaxPossible > 0) {
|
| pourcentage = Math.round((scoreTotal / scoreMaxPossible) * 100);
|
| }
|
|
|
| console.log(`Pourcentage calculé: ${pourcentage}%`);
|
|
|
| const barre = document.getElementById("trustBar");
|
| if (barre) {
|
| barre.style.width = pourcentage + "%";
|
| barre.textContent = pourcentage + "%";
|
|
|
| if (pourcentage < 40) {
|
| barre.style.background = "#E53935";
|
| barre.title = `Faible confiance (${pourcentage}%)`;
|
| } else if (pourcentage < 70) {
|
| barre.style.background = "#FB8C00";
|
| barre.title = `Confiance moyenne (${pourcentage}%)`;
|
| } else {
|
| barre.style.background = "#43A047";
|
| barre.title = `Forte confiance (${pourcentage}%)`;
|
| }
|
|
|
| console.log(`Barre mise à jour: ${pourcentage}% (width: ${pourcentage}%)`);
|
| } else {
|
| console.error("Élément #trustBar non trouvé!");
|
| }
|
|
|
| const avgTrustElem = document.getElementById("avgTrustScore");
|
| if (avgTrustElem) {
|
| avgTrustElem.textContent = pourcentage + "%";
|
| console.log(`Statistique moyenne mise à jour: ${pourcentage}%`);
|
| }
|
|
|
| console.log("=== RÉSUMÉ FINAL ===");
|
| console.log(`Indice global de confiance: ${pourcentage}%`);
|
| console.log("Valeurs des métriques:", JSON.stringify(trustMetrics, null, 2));
|
| console.log("====================");
|
|
|
| return pourcentage;
|
| }
|
|
|
| function initTrustSave(){
|
| const saveBtn = document.getElementById("saveTrustBtn");
|
| if (!saveBtn) {
|
| console.error("Bouton de sauvegarde non trouvé!");
|
| return;
|
| }
|
|
|
| saveBtn.onclick = () => {
|
| console.log("=== DÉBUT SAUVEGARDE ===");
|
|
|
| const gdprAccept = document.getElementById('gdprAccept').checked;
|
| const gdprDecline = document.getElementById('gdprDecline').checked;
|
|
|
| let evaluatorName = "";
|
| let evaluatorEmail = "";
|
| let evaluatorRole = "";
|
| let expertiseLevel = "";
|
| let messageMastery = "";
|
|
|
| if (gdprAccept) {
|
| evaluatorName = document.getElementById("evaluatorName").value.trim();
|
| evaluatorEmail = document.getElementById("evaluatorEmail").value.trim();
|
| evaluatorRole = document.getElementById("evaluatorRole").value;
|
| expertiseLevel = document.getElementById("expertiseLevel").value;
|
| messageMastery = document.getElementById("messageMastery").value;
|
| }
|
|
|
| const comment = document.getElementById("trustComment").value;
|
| const msgDiv = document.getElementById("saveTrustMsg");
|
|
|
| if (!gdprAccept && !gdprDecline) {
|
| const message = "❌ Veuillez sélectionner une option de consentement RGPD.";
|
| console.error(message);
|
|
|
| if (msgDiv) {
|
| msgDiv.textContent = message;
|
| msgDiv.style.background = "#FFEBEE";
|
| msgDiv.style.color = "#C62828";
|
| }
|
| return;
|
| }
|
|
|
| if (gdprAccept) {
|
| if (!evaluatorRole) {
|
| const message = "❌ Veuillez sélectionner votre rôle.";
|
| console.error(message);
|
|
|
| if (msgDiv) {
|
| msgDiv.textContent = message;
|
| msgDiv.style.background = "#FFEBEE";
|
| msgDiv.style.color = "#C62828";
|
| }
|
| return;
|
| }
|
|
|
| if (!expertiseLevel) {
|
| const message = "❌ Veuillez sélectionner votre niveau d'expertise en réflexivité.";
|
| console.error(message);
|
|
|
| if (msgDiv) {
|
| msgDiv.textContent = message;
|
| msgDiv.style.background = "#FFEBEE";
|
| msgDiv.style.color = "#C62828";
|
| }
|
| return;
|
| }
|
|
|
| if (!messageMastery) {
|
| const message = "❌ Veuillez sélectionner votre niveau de maîtrise de l'apprentissage auto-régulé.";
|
| console.error(message);
|
|
|
| if (msgDiv) {
|
| msgDiv.textContent = message;
|
| msgDiv.style.background = "#FFEBEE";
|
| msgDiv.style.color = "#C62828";
|
| }
|
| return;
|
| }
|
| }
|
|
|
| let hasEvaluation = false;
|
| for (const metric in trustMetrics) {
|
| if (trustMetrics[metric] > 0) {
|
| hasEvaluation = true;
|
| break;
|
| }
|
| }
|
|
|
| if (!hasEvaluation) {
|
| const message = "⚠️ Veuillez évaluer au moins une métrique avant de sauvegarder.";
|
| console.warn(message);
|
|
|
| if (msgDiv) {
|
| msgDiv.textContent = message;
|
| msgDiv.style.background = "#FFF3E0";
|
| msgDiv.style.color = "#EF6C00";
|
| }
|
| return;
|
| }
|
|
|
| const trustScore = updateTrustBar();
|
|
|
| console.log(`Indice calculé pour sauvegarde: ${trustScore}%`);
|
|
|
| const data = {
|
| timestamp: new Date().toISOString(),
|
| scenario_id: scenarios[currentScenarioIndex].id,
|
| scenario_title: scenarios[currentScenarioIndex].title,
|
| ar: trustMetrics["AR"],
|
| ae: trustMetrics["AE"],
|
| esr: trustMetrics["ESR"],
|
| sdm: trustMetrics["SDM"],
|
| sm: trustMetrics["SM"],
|
| trust_score: trustScore,
|
| comment: comment || "",
|
| consent: gdprAccept ? "accept" : "decline",
|
| evaluator_name: gdprAccept ? (evaluatorName || "") : "",
|
| evaluator_email: gdprAccept ? (evaluatorEmail || "") : "",
|
| role: gdprAccept ? evaluatorRole : "",
|
| expertise_reflexivite: gdprAccept ? expertiseLevel : "",
|
| maitrise_srl: gdprAccept ? messageMastery : ""
|
| };
|
|
|
| console.log("Données à envoyer:", JSON.stringify(data, null, 2));
|
|
|
| if (msgDiv) {
|
| msgDiv.innerHTML = `
|
| <div style="display: flex; align-items: center; gap: 10px;">
|
| <div class="loading"></div>
|
| <div>Envoi en cours vers le serveur...</div>
|
| </div>
|
| `;
|
| msgDiv.style.background = "#E3F2FD";
|
| msgDiv.style.color = "#1976D2";
|
| }
|
|
|
| fetch(GOOGLE_SCRIPT_URL, {
|
| method: 'POST',
|
| mode: 'no-cors',
|
| headers: {
|
| 'Content-Type': 'application/x-www-form-urlencoded',
|
| },
|
| body: new URLSearchParams(data)
|
| })
|
| .then(() => {
|
| console.log("✅ Données envoyées avec succès");
|
|
|
| if (msgDiv) {
|
| const nameDisplay = gdprAccept ? (evaluatorName || "Évaluateur") : "Évaluateur anonyme";
|
| msgDiv.innerHTML = `
|
| <div style="display: flex; align-items: center; gap: 10px;">
|
| <div style="font-size: 24px;">✅</div>
|
| <div>
|
| <strong>Évaluation sauvegardée avec succès !</strong><br>
|
| <small>Merci ${nameDisplay} pour votre contribution.</small><br>
|
| <small><em>Indice global: ${trustScore}%</em></small>
|
| </div>
|
| </div>
|
| `;
|
| msgDiv.style.background = "#E8F5E9";
|
| msgDiv.style.color = "#2E7D32";
|
| msgDiv.style.padding = "15px";
|
| }
|
|
|
| setTimeout(() => {
|
| if (msgDiv) {
|
| msgDiv.innerHTML = "";
|
| msgDiv.style.background = "";
|
| msgDiv.style.color = "";
|
| msgDiv.style.padding = "";
|
| }
|
| }, 5000);
|
| })
|
| .catch(error => {
|
| console.error("❌ Erreur lors de l'envoi:", error);
|
|
|
| if (msgDiv) {
|
| msgDiv.innerHTML = `
|
| <div style="display: flex; align-items: center; gap: 10px;">
|
| <div style="font-size: 24px;">❌</div>
|
| <div>
|
| <strong>Erreur lors de la sauvegarde</strong><br>
|
| <small>${error.message}</small><br>
|
| <small>Veuillez réessayer ou contacter l'administrateur.</small>
|
| </div>
|
| </div>
|
| `;
|
| msgDiv.style.background = "#FFEBEE";
|
| msgDiv.style.color = "#C62828";
|
| msgDiv.style.padding = "15px";
|
| }
|
| });
|
| };
|
|
|
| console.log("✅ Bouton de sauvegarde initialisé avec Google Sheets");
|
| }
|
|
|
| function resetTrustEvaluation() {
|
| console.log("Réinitialisation de l'évaluation...");
|
|
|
| for (const key in trustMetrics) {
|
| trustMetrics[key] = 0;
|
| }
|
|
|
| document.querySelectorAll(".stars").forEach(div => {
|
| Array.from(div.children).forEach(star => {
|
| star.classList.add("inactive");
|
| star.classList.remove("active");
|
| });
|
| });
|
|
|
| updateTrustBar();
|
|
|
| const commentField = document.getElementById("trustComment");
|
| if (commentField) {
|
| commentField.value = "";
|
| }
|
|
|
| console.log("Évaluation réinitialisée");
|
| }
|
|
|
|
|
|
|
| function updateStats(scenario) {
|
| if (!scenario) return;
|
|
|
| const currentScenarioNum = document.getElementById("currentScenarioNum");
|
| const riskLevelElem = document.getElementById("riskLevel");
|
| const avgActivityElem = document.getElementById("avgActivity");
|
|
|
| if (currentScenarioNum) {
|
| currentScenarioNum.textContent = scenario.id || "-";
|
| }
|
|
|
| if (riskLevelElem) {
|
| const risk = scenario.risk || 50;
|
| let riskLevel = "Moyen";
|
| let riskColor = "#FB8C00";
|
|
|
| if (risk < 40) {
|
| riskLevel = "Faible";
|
| riskColor = "#43A047";
|
| } else if (risk > 70) {
|
| riskLevel = "Élevé";
|
| riskColor = "#E53935";
|
| }
|
|
|
| riskLevelElem.textContent = riskLevel;
|
| riskLevelElem.style.color = riskColor;
|
| }
|
|
|
| if (avgActivityElem && scenario.radar && scenario.radar.length > 0) {
|
| const filteredRadar = scenario.radar.filter(metric => metric.label !== "Engagement global");
|
| const avgRadar = filteredRadar.reduce((sum, item) => sum + item.value, 0) / filteredRadar.length;
|
| avgActivityElem.textContent = Math.round(avgRadar) + "%";
|
| }
|
| }
|
|
|
| function fillSampleEvaluator() {
|
| document.getElementById('gdprAccept').checked = true;
|
| document.getElementById('gdprDecline').checked = false;
|
|
|
| initGDPR();
|
|
|
| document.getElementById("evaluatorName").value = "Martin Sophie";
|
| document.getElementById("evaluatorEmail").value = "sophie.martin@exemple.fr";
|
| document.getElementById("evaluatorRole").value = "enseignant";
|
| document.getElementById("messageMastery").value = "intermediaire_srl";
|
| document.getElementById("expertiseLevel").value = "avance";
|
|
|
| showNotification("Exemple", "Champs d'évaluateur remplis avec un exemple", "info");
|
| }
|
|
|
| function clearEvaluatorFields() {
|
| document.getElementById('gdprDecline').checked = true;
|
| document.getElementById('gdprAccept').checked = false;
|
|
|
| initGDPR();
|
|
|
| showNotification("Champs effacés", "Les informations d'évaluateur ont été effacées", "info");
|
| }
|
|
|
| function showNotification(title, message, type = "info") {
|
| console.log(`[${type}] ${title}: ${message}`);
|
|
|
| const msgDiv = document.getElementById("saveTrustMsg");
|
| if (msgDiv) {
|
| msgDiv.textContent = `${title}: ${message}`;
|
| msgDiv.style.background = type === "success" ? "#E8F5E9" :
|
| type === "error" ? "#FFEBEE" : "#E3F2FD";
|
| msgDiv.style.color = type === "success" ? "#2E7D32" :
|
| type === "error" ? "#C62828" : "#1565C0";
|
|
|
| setTimeout(() => {
|
| msgDiv.textContent = "";
|
| msgDiv.style.background = "";
|
| msgDiv.style.color = "";
|
| }, 5000);
|
| }
|
| }
|
|
|
| function changePersistenceAnalysis() {
|
| const modeSelect = document.getElementById("persistenceMode");
|
| if (!modeSelect) return;
|
|
|
| const mode = modeSelect.value;
|
| const currentScenario = scenarios[currentScenarioIndex];
|
|
|
| if (!currentScenario) return;
|
|
|
| drawCompactEnrichedHeatmapWithAxes(currentScenario);
|
|
|
| updatePersistenceIndicators(mode);
|
| }
|
|
|
| window.changePersistenceAnalysis = changePersistenceAnalysis;
|
| window.updateStats = updateStats;
|
| window.showNotification = showNotification;
|
| window.fillSampleEvaluator = fillSampleEvaluator;
|
| window.clearEvaluatorFields = clearEvaluatorFields;
|
| window.loadScenario = loadScenario;
|
| window.playRadarNarration = playRadarNarration;
|
| window.pauseRadarNarration = pauseRadarNarration;
|
| window.stopRadarNarration = stopRadarNarration;
|
| window.playHeatmapNarration = playHeatmapNarration;
|
| window.pauseHeatmapNarration = pauseHeatmapNarration;
|
| window.stopHeatmapNarration = stopHeatmapNarration;
|
| </script>
|
|
|
| </div>
|
|
|
| <div style="
|
| margin-top: 40px;
|
| padding: 20px;
|
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
| border-top: 1px solid #e0e0e0;
|
| text-align: center;
|
| color: #666;
|
| font-size: 14px;
|
| line-height: 1.6;
|
| border-radius: 0 0 20px 20px;
|
| ">
|
| <div style="font-weight: bold; color: #1976D2; margin-bottom: 8px;">
|
| Laboratoire d'informatique de l'Université du Mans
|
| </div>
|
| <div>Bâtiment IC2</div>
|
| <div>Avenue Olivier Messiaen</div>
|
| <div>F-72085 - LE MANS CEDEX 9</div>
|
| <div>Tél : +33 (0) 2 43 83 38 58</div>
|
| </div>
|
|
|
| </body>
|
| </html> |