| <!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;
|
| }
|
|
|
| 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;
|
| }
|
|
|
| .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;
|
| }
|
|
|
| .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;
|
| }
|
|
|
|
|
| .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;
|
| }
|
|
|
| #scenarioTitle {
|
| font-size: 1.4em;
|
| color: #333;
|
| text-align: center;
|
| flex-grow: 1;
|
| margin: 0 20px;
|
| }
|
|
|
| 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;
|
| }
|
|
|
| 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;
|
| }
|
|
|
|
|
| #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;
|
| }
|
|
|
|
|
| #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: 15px;
|
| border-radius: 12px;
|
| border: 1px solid #e0e0e0;
|
| margin: 15px 0;
|
| }
|
|
|
| .compact-competences-grid {
|
| display: grid;
|
| grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
| gap: 12px;
|
| margin: 10px 0;
|
| }
|
|
|
| .compact-competence-item {
|
| padding: 10px;
|
| background: #f8f9fa;
|
| border-radius: 8px;
|
| border-left: 4px solid #1976D2;
|
| transition: transform 0.2s;
|
| }
|
|
|
| .compact-competence-item:hover {
|
| transform: translateY(-2px);
|
| background: #e3f2fd;
|
| }
|
|
|
| .compact-competence-label {
|
| font-size: 12px;
|
| font-weight: 600;
|
| color: #333;
|
| margin-bottom: 8px;
|
| display: flex;
|
| justify-content: space-between;
|
| }
|
|
|
| .compact-competence-bar {
|
| height: 10px;
|
| background: #e0e0e0;
|
| border-radius: 5px;
|
| overflow: hidden;
|
| margin: 5px 0;
|
| }
|
|
|
| .compact-competence-fill {
|
| height: 100%;
|
| border-radius: 5px;
|
| color: white;
|
| font-size: 9px;
|
| text-align: right;
|
| padding-right: 5px;
|
| line-height: 10px;
|
| font-weight: bold;
|
| transition: width 0.5s ease;
|
| }
|
|
|
|
|
| .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); }
|
|
|
|
|
| #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-radar-metrics-grid {
|
| display: grid;
|
| grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
| gap: 12px;
|
| margin: 15px 0;
|
| }
|
|
|
| .compact-metric-card {
|
| background: white;
|
| border-radius: 10px;
|
| padding: 15px;
|
| box-shadow: 0 3px 8px rgba(0,0,0,0.08);
|
| border-left: 4px solid #1976D2;
|
| transition: transform 0.3s;
|
| text-align: center;
|
| }
|
|
|
| .compact-metric-card:hover {
|
| transform: translateY(-3px);
|
| box-shadow: 0 5px 15px rgba(0,0,0,0.12);
|
| }
|
|
|
| .compact-metric-icon {
|
| font-size: 24px;
|
| margin-bottom: 8px;
|
| }
|
|
|
| .compact-metric-name {
|
| font-weight: 600;
|
| color: #333;
|
| margin-bottom: 5px;
|
| font-size: 14px;
|
| }
|
|
|
| .compact-metric-value {
|
| font-size: 20px;
|
| 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: 11px;
|
| color: #666;
|
| margin-top: 5px;
|
| line-height: 1.3;
|
| }
|
|
|
|
|
| .compact-heatmap-and-indicators {
|
| background: white;
|
| padding: 15px;
|
| border-radius: 12px;
|
| border: 1px solid #e0e0e0;
|
| margin: 15px 0;
|
| }
|
|
|
| .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: 15px 0;
|
| }
|
|
|
| .compact-legend-section h5 {
|
| color: #1976D2;
|
| margin-bottom: 10px;
|
| font-size: 14px;
|
| display: flex;
|
| align-items: center;
|
| gap: 6px;
|
| }
|
|
|
| .compact-legend-grid {
|
| display: grid;
|
| grid-template-columns: repeat(3, 1fr);
|
| gap: 8px;
|
| }
|
|
|
| .compact-legend-item-small {
|
| display: flex;
|
| align-items: center;
|
| gap: 6px;
|
| font-size: 11px;
|
| }
|
|
|
| .compact-legend-color-small {
|
| width: 16px;
|
| height: 16px;
|
| border-radius: 4px;
|
| border: 2px solid white;
|
| box-shadow: 0 2px 4px 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;
|
| }
|
|
|
|
|
| #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);
|
| }
|
|
|
|
|
| #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;
|
| }
|
|
|
| #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;
|
| }
|
|
|
| @keyframes shimmer {
|
| 0% { transform: translateX(-100%); }
|
| 100% { transform: translateX(100%); }
|
| }
|
|
|
|
|
| #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;
|
| }
|
|
|
|
|
| @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); }
|
| }
|
|
|
|
|
| @media (max-width: 1200px) {
|
| #reflection {
|
| padding: 20px;
|
| }
|
|
|
| .tabs {
|
| flex-direction: column;
|
| }
|
|
|
| .tab-btn {
|
| width: 100%;
|
| }
|
| }
|
|
|
| @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(auto-fill, minmax(150px, 1fr));
|
| }
|
|
|
| .compact-radar-metrics-grid {
|
| grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
| }
|
|
|
| .compact-radar-legend {
|
| flex-direction: column;
|
| align-items: center;
|
| gap: 8px;
|
| }
|
|
|
| .compact-legend-grid {
|
| grid-template-columns: repeat(2, 1fr);
|
| }
|
|
|
| .compact-analysis-controls {
|
| flex-direction: column;
|
| align-items: stretch;
|
| }
|
|
|
| .compact-persistence-indicators {
|
| flex-direction: column;
|
| }
|
| }
|
|
|
|
|
| .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);
|
| }
|
|
|
|
|
| .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;
|
| }
|
|
|
| @keyframes spin {
|
| 0% { transform: rotate(0deg); }
|
| 100% { transform: rotate(360deg); }
|
| }
|
|
|
|
|
| .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;
|
| }
|
| </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-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>
|
| </div>
|
|
|
|
|
| <div id="tab-evaluator" class="tab-content active">
|
| <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 <span style="color: #e53935;">*</span></strong>
|
| </label>
|
| <input type="text"
|
| id="evaluatorName"
|
| placeholder="Ex: Dupont Jean ou Marie Curie"
|
| maxlength="100"
|
| disabled>
|
| <small>Veuillez saisir votre nom et prénom</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="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>
|
| <option value="chercheur_reflex">Chercheur en réflexivité</option>
|
| </select>
|
| <small>Indiquez votre niveau de maîtrise des concepts et outils de réflexivité</small>
|
| </div>
|
|
|
|
|
| <div class="evaluator-field">
|
| <label for="messageMastery"><strong><span style="color: #1976D2; margin-right: 5px;">💬</span> Niveau de maîtrise des messages réflexifs <span style="color: #e53935;">*</span></strong></label>
|
| <select id="messageMastery" disabled>
|
| <option value="">Sélectionnez votre niveau...</option>
|
| <option value="novice">Novice - Je commence à analyser des messages réflexifs</option>
|
| <option value="intermediaire_msg">Intermédiaire - J'évalue régulièrement des feedbacks réflexifs</option>
|
| <option value="avance_msg">Avancé - Je rédige des messages réflexifs pour autrui</option>
|
| <option value="expert_msg">Expert - Je forme à la conception de messages réflexifs</option>
|
| </select>
|
| <small>Indiquez votre expérience avec l'analyse et la création de messages réflexifs</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;">
|
| <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>🕸️ Radar – Learning Analytics</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 class="compact-radar-bot-message" style="flex: 1; min-width: 300px;">
|
| <div class="compact-radar-bot-header">
|
| <div class="compact-radar-bot-icon">🎯</div>
|
| <h4 class="compact-radar-bot-title">Analyse de Profil</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 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>
|
| </div>
|
|
|
|
|
| <div class="compact-heatmap-and-indicators">
|
| <h3>🔥 Heatmap d'activité - Analyse de Persévérance</h3>
|
|
|
| <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">🎯 Vue combinée</option>
|
| </select>
|
| </div>
|
|
|
|
|
| <canvas id="heatmap" width="800" height="250" style="max-width: 100%; height: auto;"></canvas>
|
| </div>
|
|
|
|
|
| <div class="compact-enriched-legend">
|
| <div class="compact-legend-section">
|
| <h5>📈 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 activité</span>
|
| </div>
|
| <div class="compact-legend-item-small">
|
| <div class="compact-legend-color-small" style="background:#C6E48B;"></div>
|
| <span>Faible activité</span>
|
| </div>
|
| <div class="compact-legend-item-small">
|
| <div class="compact-legend-color-small" style="background:#7BC96F;"></div>
|
| <span>Activité modérée</span>
|
| </div>
|
| <div class="compact-legend-item-small">
|
| <div class="compact-legend-color-small" style="background:#239A3B;"></div>
|
| <span>Activité élevée</span>
|
| </div>
|
| <div class="compact-legend-item-small">
|
| <div class="compact-legend-color-small" style="background:#196127;"></div>
|
| <span>Activité intense</span>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
|
|
| <div class="compact-persistence-analysis" id="compact-persistenceAnalysis">
|
| <h5>🎯 Indicateurs de Persévérance</h5>
|
| <div class="compact-persistence-indicators">
|
| <div class="compact-indicator">
|
| <span class="compact-indicator-dot" style="background:#FF6B6B;"></span>
|
| <span>Régularité : <strong id="compact-regularityScore">-</strong></span>
|
| </div>
|
| <div class="compact-indicator">
|
| <span class="compact-indicator-dot" style="background:#4ECDC4;"></span>
|
| <span>Schéma d'effort : <strong id="compact-effortPattern">-</strong></span>
|
| </div>
|
| <div class="compact-indicator">
|
| <span class="compact-indicator-dot" style="background:#FFD166;"></span>
|
| <span>Gestion échéances : <strong id="compact-deadlineScore">-</strong></span>
|
| </div>
|
| </div>
|
|
|
| <div class="compact-persistence-text" style="margin-top: 10px;">
|
| <div><strong>Régularité :</strong> <span id="compact-regularityText">Analyse en cours...</span></div>
|
| <div><strong>Schéma d'effort :</strong> <span id="compact-patternText">Analyse en cours...</span></div>
|
| </div>
|
| </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;">
|
| L'analyse reflète-t-elle fidèlement la situation réelle de l'étudiant ?
|
| </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;">
|
| L'agent comprend-il les émotions, motivations et difficultés de l'étudiant ?
|
| </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;">
|
| Les encouragements tiennent-ils compte des risques et difficultés identifiés ?
|
| </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;">
|
| L'agent aide-t-il l'étudiant à développer sa pensée critique et ses compétences cognitives ?
|
| </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;">
|
| L'agent aide-t-il l'étudiant à réfléchir sur ses propres stratégies d'apprentissage ?
|
| </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;">
|
| <div style="flex-grow: 1; margin-right: 20px;">
|
| <h4 style="margin-bottom: 10px;">🔒 Indice global de confiance</h4>
|
| <div class="progress-container">
|
| <div class="fill" 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;">
|
| <button id="saveTrustBtn" style="height: fit-content; width: 100%;">💾 Sauvegarder l'évaluation</button>
|
| <button id="crossReadersBtn" style="height: fit-content; width: 100%; background: linear-gradient(135deg, #43A047, #4CAF50);">
|
| 📊 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>
|
| </div>
|
|
|
|
|
| <script>
|
|
|
| let scenarios = [];
|
| let currentScenarioIndex = 0;
|
| let radarMetrics = [];
|
|
|
|
|
| const DEFAULT_RADAR_METRICS = [
|
| { label: "Démarrage des activités", value: 85 },
|
| { label: "Connaissances validées", value: 72 },
|
| { label: "Niveau moyen de compétence", value: 68 },
|
| { label: "Taux d'erreur (inversé)", value: 35 },
|
| { label: "Achèvement des activités", value: 74 },
|
| { label: "Interactions avec les ressources", value: 80 },
|
| { label: "Domaines de compétence", 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
|
| };
|
|
|
|
|
| document.addEventListener("DOMContentLoaded", () => {
|
| console.log("✅ DOM chargé, initialisation...");
|
| loadScenarios();
|
| initTrustStars();
|
| initTrustSave();
|
| initTabs();
|
| initGDPR();
|
|
|
|
|
| updateTrustBar();
|
| });
|
|
|
|
|
| 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('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('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 = '';
|
| }
|
| }
|
|
|
|
|
| gdprAccept.addEventListener('change', updateGDPRFields);
|
| gdprDecline.addEventListener('change', updateGDPRFields);
|
|
|
|
|
| updateGDPRFields();
|
| }
|
|
|
|
|
| function loadScenarios() {
|
| console.log("Chargement des scénarios...");
|
| fetch("/static/scenarios.json")
|
| .then(r => {
|
| if (!r.ok) throw new Error("Erreur de chargement du fichier JSON");
|
| return r.json();
|
| })
|
| .then(data => {
|
| console.log("Scénarios chargés:", data.scenarios.length);
|
| scenarios = data.scenarios;
|
| loadScenario(0);
|
| })
|
| .catch(error => {
|
| console.error("Erreur:", error);
|
| document.getElementById("manifest-list").innerHTML =
|
| `<div class="manifest-item" style="background:#FFEBEE;color:#C62828;">
|
| Erreur de chargement des scénarios. Vérifiez que le fichier scenarios.json existe.
|
| </div>`;
|
| });
|
| }
|
|
|
|
|
| function loadScenario(index) {
|
| console.log("Chargement scénario", index);
|
| if (index < 0 || index >= scenarios.length) return;
|
| currentScenarioIndex = index;
|
| const s = scenarios[index];
|
|
|
|
|
| const titleElement = document.getElementById("scenarioTitle");
|
| titleElement.textContent = `Scénario ${s.id} – ${s.title}`;
|
|
|
|
|
| document.getElementById("manifest-list").innerHTML = `
|
| <div class="manifest-item">
|
| <b>Type de Manifest :</b> ${s.manifest.type}<br>
|
| <b>Manifeste (écrit par l'étudiant) :</b> ${s.manifest.manifeste}<br>
|
| <b>Description du Profil :</b> ${s.manifest.description}
|
| </div>`;
|
|
|
|
|
| updateCompactCompetences(s.competences);
|
|
|
|
|
| if (s.radar && s.radar.length > 0) {
|
| radarMetrics = s.radar;
|
| } 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);
|
|
|
|
|
| drawCompactEnrichedHeatmap(s);
|
|
|
|
|
| document.getElementById("reflagent").textContent = s.reflAgent;
|
|
|
|
|
| updateNavButtons();
|
|
|
|
|
| updateStats();
|
| }
|
|
|
|
|
|
|
|
|
| function updateCompactCompetences(competences) {
|
| const container = document.getElementById("compact-competences");
|
| if (!container) return;
|
|
|
| container.innerHTML = '';
|
|
|
| competences.forEach(comp => {
|
|
|
| let color;
|
| if (comp.value < 50) color = '#E53935';
|
| else if (comp.value < 70) color = '#FB8C00';
|
| else color = '#43A047';
|
|
|
|
|
| const compItem = document.createElement('div');
|
| compItem.className = 'compact-competence-item';
|
| compItem.innerHTML = `
|
| <div class="compact-competence-label">
|
| <span>${comp.label}</span>
|
| <span>${comp.value}%</span>
|
| </div>
|
| <div class="compact-competence-bar">
|
| <div class="compact-competence-fill" style="width: ${comp.value}%; background: ${color};">
|
| ${comp.value >= 10 ? comp.value + '%' : ''}
|
| </div>
|
| </div>
|
| `;
|
|
|
| container.appendChild(compItem);
|
| });
|
| }
|
|
|
|
|
| function updateCompactRadarMetricsGrid() {
|
| const grid = document.getElementById("compact-radar-metrics-grid");
|
| if (!grid) return;
|
|
|
| grid.innerHTML = '';
|
|
|
| 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("Connaissances")) 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("Domaines")) icon = "🔧";
|
|
|
|
|
| let description = "";
|
| if (metric.label.includes("Démarrage")) description = "Rapidité d'initiation";
|
| else if (metric.label.includes("Connaissances")) description = "Acquis démontrés";
|
| else if (metric.label.includes("Niveau moyen")) description = "Moyenne 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 = "Utilisation supports";
|
| else if (metric.label.includes("Domaines")) description = "Étendue couverte";
|
|
|
| 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 profileMessages = {
|
| "Étudiant engagé": {
|
| title: "Étudiant Engagé et Motivé",
|
| message: "🎯 Ton engagement est impressionnant ! Tu démontres une forte volonté d'apprendre.",
|
| insights: [
|
| { icon: "🔥", text: "Motivation élevée" },
|
| { icon: "🎯", text: "Objectifs bien définis" },
|
| { icon: "📚", text: "Implication active" }
|
| ]
|
| },
|
| "Étudiant actif mais inefficace": {
|
| title: "Actif mais Peu Efficace",
|
| message: "📊 Tu es très actif mais ton taux d'erreur est élevé. Concentre-toi sur une compétence à la fois.",
|
| insights: [
|
| { icon: "⚡", text: "Activité élevée" },
|
| { icon: "⚠️", text: "Erreurs fréquentes" },
|
| { icon: "🎯", text: "Focus nécessaire" }
|
| ]
|
| },
|
| "Étudiant orienté vers le succès": {
|
| title: "Orientation Réussite",
|
| message: "🏆 Tu vises l'excellence avec détermination. Ta rigueur est exemplaire.",
|
| insights: [
|
| { icon: "⭐", text: "Excellence visée" },
|
| { icon: "🎯", text: "Objectifs ambitieux" },
|
| { icon: "📈", text: "Performance supérieure" }
|
| ]
|
| },
|
| "Étudiant motivé": {
|
| title: "Nouvellement Motivé",
|
| message: "🚀 Ta motivation est un excellent point de départ ! Progresse étape par étape.",
|
| insights: [
|
| { icon: "🌟", text: "Motivation récente" },
|
| { icon: "🧱", text: "Construction des bases" },
|
| { icon: "📖", text: "Curiosité ouverte" }
|
| ]
|
| },
|
| "Étudiant surmotivé": {
|
| title: "Surmotivé - Attention",
|
| message: "💥 Ton niveau d'investissement est exceptionnel, attention au risque de surmenage.",
|
| insights: [
|
| { icon: "⚡", text: "Investissement maximal" },
|
| { icon: "⚠️", text: "Risque de burnout" },
|
| { icon: "⚖️", text: "Équilibre nécessaire" }
|
| ]
|
| },
|
| "Étudiant stratégique": {
|
| title: "Stratégique et Efficient",
|
| message: "♟️ Tu abordes l'apprentissage avec intelligence et planification.",
|
| insights: [
|
| { icon: "🧠", text: "Approche réfléchie" },
|
| { icon: "🎯", text: "Optimisation efforts" },
|
| { icon: "📊", text: "Analyse des retours" }
|
| ]
|
| }
|
| };
|
|
|
|
|
| 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 drawCompactEnrichedHeatmap(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é"
|
| }
|
| };
|
|
|
| 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, 20);
|
|
|
| ctx.font = "12px Arial";
|
| ctx.fillStyle = "#666";
|
| ctx.fillText(`${scenarioInfo.pattern}`, canvas.width / 2, 40);
|
|
|
|
|
| const activityData = generateCompactPersistenceData(scenario.id, totalDays);
|
|
|
|
|
| const colors = ["#EBEDF0", "#C6E48B", "#7BC96F", "#239A3B", "#196127"];
|
|
|
| for (let day = 0; day < totalDays; day++) {
|
| const week = Math.floor(day / 7);
|
| const weekday = day % 7;
|
|
|
| const x = 30 + week * (cellSize * 7 + padding * 7) + weekday * (cellSize + padding);
|
| const y = 60 + 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);
|
| }
|
|
|
|
|
| function generateCompactPersistenceData(scenarioId, totalDays) {
|
| const data = new Array(totalDays).fill(0);
|
|
|
| switch(scenarioId) {
|
| case 1:
|
| for (let i = 0; i < totalDays; i++) {
|
| const weekday = i % 7;
|
| if (weekday === 3 || weekday === 4) {
|
| data[i] = Math.floor(Math.random() * 2) + 3;
|
| } else if (weekday === 5 || weekday === 6) {
|
| data[i] = Math.floor(Math.random() * 2);
|
| } else {
|
| data[i] = Math.floor(Math.random() * 2) + 1;
|
| }
|
| }
|
| break;
|
|
|
| case 2:
|
| for (let i = 0; i < totalDays; i++) {
|
| const progress = i / totalDays;
|
| if (progress < 0.3) {
|
| data[i] = Math.floor(Math.random() * 2);
|
| } else if (progress > 0.7) {
|
| data[i] = Math.floor(Math.random() * 2) + 3;
|
| } else {
|
| data[i] = Math.floor(Math.random() * 2) + 1;
|
| }
|
| }
|
| break;
|
|
|
| case 3:
|
| for (let i = 0; i < totalDays; i++) {
|
| const weekday = i % 7;
|
| if (weekday === 5 || weekday === 6) {
|
| data[i] = Math.floor(Math.random() * 2);
|
| } else {
|
| data[i] = Math.floor(Math.random() * 2) + 2;
|
| }
|
| }
|
| break;
|
|
|
| default:
|
| for (let i = 0; i < totalDays; i++) {
|
| data[i] = Math.floor(Math.random() * 5);
|
| }
|
| }
|
|
|
| return data;
|
| }
|
|
|
|
|
| function analyzeCompactPersistenceMetrics(activityData, scenarioId) {
|
| const totalDays = activityData.length;
|
|
|
|
|
| const avgActivity = activityData.reduce((a, b) => a + b, 0) / totalDays;
|
| const variance = activityData.reduce((a, b) => a + Math.pow(b - avgActivity, 2), 0) / totalDays;
|
| const stdDev = Math.sqrt(variance);
|
| const regularity = Math.max(0, 100 - stdDev * 25);
|
|
|
|
|
| let pattern = "Régulier";
|
| let patternDescription = "Effort équilibré toute la semaine";
|
|
|
|
|
| const weeklyPatterns = [];
|
| for (let w = 0; w < 4; w++) {
|
| const weekData = activityData.slice(w * 7, Math.min((w + 1) * 7, totalDays));
|
| if (weekData.length < 5) continue;
|
|
|
| const weekAvg = weekData.reduce((a, b) => a + b, 0) / weekData.length;
|
|
|
| if (weekData[4] > weekAvg * 1.5 && weekData[3] > weekAvg * 1.3) {
|
| pattern = "Effort concentré";
|
| patternDescription = "Pic d'activité jeudi/vendredi";
|
| } else if (weekData[0] < weekAvg * 0.7 && weekData[4] > weekAvg * 1.2) {
|
| pattern = "Accélération progressive";
|
| patternDescription = "Démarrage lent, fin forte";
|
| }
|
| }
|
|
|
|
|
| const deadlineDays = activityData.filter((_, index) => index % 7 === 3 || index % 7 === 4);
|
| const nonDeadlineDays = activityData.filter((_, index) => index % 7 !== 3 && index % 7 !== 4);
|
|
|
| let deadlineScore = 50;
|
| if (deadlineDays.length > 0 && nonDeadlineDays.length > 0) {
|
| const deadlineAvg = deadlineDays.reduce((a, b) => a + b, 0) / deadlineDays.length;
|
| const nonDeadlineAvg = nonDeadlineDays.reduce((a, b) => a + b, 0) / nonDeadlineDays.length;
|
| deadlineScore = Math.min(100, Math.max(0, (deadlineAvg / 4) * 100));
|
| }
|
|
|
|
|
| document.getElementById("compact-regularityScore").textContent = Math.round(regularity) + "%";
|
| document.getElementById("compact-effortPattern").textContent = pattern;
|
| document.getElementById("compact-deadlineScore").textContent = Math.round(deadlineScore) + "%";
|
|
|
|
|
| document.getElementById("compact-regularityText").textContent =
|
| regularity > 75 ? "Excellente régularité" :
|
| regularity > 60 ? "Bonne régularité" :
|
| regularity > 40 ? "Régularité moyenne" :
|
| "Faible régularité";
|
|
|
| document.getElementById("compact-patternText").textContent = patternDescription;
|
| }
|
|
|
|
|
| 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 = 200;
|
| 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();
|
| }
|
|
|
|
|
| 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";
|
| ctx.fillText(`${m.label.split(' ')[0]}`, 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();
|
| });
|
| }
|
|
|
|
|
| document.getElementById("prevScenario").onclick = () =>
|
| loadScenario(currentScenarioIndex - 1);
|
|
|
| document.getElementById("nextScenario").onclick = () =>
|
| loadScenario(currentScenarioIndex + 1);
|
|
|
| function updateNavButtons() {
|
| document.getElementById("prevScenario").disabled =
|
| currentScenarioIndex === 0;
|
| document.getElementById("nextScenario").disabled =
|
| currentScenarioIndex === scenarios.length - 1;
|
| }
|
|
|
|
|
| document.getElementById('crossReadersBtn').onclick = () => {
|
| 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(() => {
|
| window.location.href = 'cross_reading/cross_readers.html';
|
| }, 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.onclick = function() {
|
| const value = parseInt(this.dataset.value);
|
| 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 evaluatorRole = "";
|
| let expertiseLevel = "";
|
| let messageMastery = "";
|
|
|
| if (gdprAccept) {
|
| evaluatorName = document.getElementById("evaluatorName").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 (!evaluatorName) {
|
| const message = "❌ Veuillez saisir votre nom et prénom.";
|
| console.error(message);
|
|
|
| if (msgDiv) {
|
| msgDiv.textContent = message;
|
| msgDiv.style.background = "#FFEBEE";
|
| msgDiv.style.color = "#C62828";
|
| }
|
|
|
| const nameField = document.getElementById("evaluatorName");
|
| nameField.style.borderColor = "#E53935";
|
| nameField.style.boxShadow = "0 0 0 3px rgba(229, 57, 53, 0.1)";
|
| nameField.focus();
|
|
|
| setTimeout(() => {
|
| nameField.style.borderColor = "#e0e0e0";
|
| nameField.style.boxShadow = "none";
|
| }, 3000);
|
|
|
| return;
|
| }
|
|
|
| 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 des messages réflexifs.";
|
| 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 = {
|
| scenario_id: scenarios[currentScenarioIndex].id,
|
| scenario_title: scenarios[currentScenarioIndex].title,
|
| trust_metrics: {...trustMetrics},
|
| trust_score: trustScore,
|
| gdpr_consent: gdprAccept ? "accept" : "decline",
|
| evaluator_name: gdprAccept ? evaluatorName : null,
|
| evaluator_role: gdprAccept ? evaluatorRole : null,
|
| expertise_level: gdprAccept ? expertiseLevel : null,
|
| message_mastery: gdprAccept ? messageMastery : null,
|
| comment: comment || null,
|
| timestamp: new Date().toISOString(),
|
| trust_weights: {...trustWeights}
|
| };
|
|
|
| console.log("Données à envoyer:", JSON.stringify(data, null, 2));
|
|
|
|
|
| fetch("/save_trust", {
|
| method: "POST",
|
| headers: { "Content-Type": "application/json" },
|
| body: JSON.stringify(data)
|
| })
|
| .then(res => {
|
| if (!res.ok) throw new Error(`Erreur HTTP ${res.status}: ${res.statusText}`);
|
| return res.json();
|
| })
|
| .then(responseData => {
|
| console.log("✅ Réponse du serveur:", responseData);
|
|
|
| if (msgDiv) {
|
| const nameDisplay = gdprAccept ? evaluatorName : "É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(() => {
|
| resetTrustEvaluation();
|
| }, 3000);
|
| })
|
| .catch(error => {
|
| console.error("❌ Erreur de sauvegarde:", error);
|
| if (msgDiv) {
|
| msgDiv.textContent = `❌ Erreur: ${error.message}`;
|
| msgDiv.style.background = "#FFEBEE";
|
| msgDiv.style.color = "#C62828";
|
| }
|
| });
|
| };
|
|
|
| console.log("✅ Bouton de sauvegarde initialisé");
|
| }
|
|
|
|
|
| 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();
|
|
|
|
|
| document.getElementById("trustComment").value = "";
|
|
|
| console.log("Évaluation réinitialisée");
|
| }
|
|
|
|
|
|
|
|
|
| function updateStats() {
|
| if (!scenarios || scenarios.length === 0) return;
|
|
|
| const currentScenario = scenarios[currentScenarioIndex];
|
|
|
| document.getElementById("currentScenarioNum").textContent = currentScenario.id;
|
|
|
|
|
| const risk = currentScenario.risk || 50;
|
| let riskLevel = "Moyen";
|
| let riskColor = "#FB8C00";
|
|
|
| if (risk < 40) {
|
| riskLevel = "Faible";
|
| riskColor = "#43A047";
|
| } else if (risk > 70) {
|
| riskLevel = "Élevé";
|
| riskColor = "#E53935";
|
| }
|
|
|
| document.getElementById("riskLevel").textContent = riskLevel;
|
| document.getElementById("riskLevel").style.color = riskColor;
|
|
|
|
|
| if (currentScenario.radar && currentScenario.radar.length > 0) {
|
| const avgRadar = currentScenario.radar.reduce((sum, item) => sum + item.value, 0) / currentScenario.radar.length;
|
| document.getElementById("avgActivity").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("evaluatorRole").value = "enseignant";
|
| document.getElementById("expertiseLevel").value = "avance";
|
| document.getElementById("messageMastery").value = "intermediaire_msg";
|
|
|
| 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";
|
| }
|
| }
|
|
|
|
|
| function changePersistenceAnalysis() {
|
| const mode = document.getElementById("persistenceMode").value;
|
| const currentScenario = scenarios[currentScenarioIndex];
|
|
|
|
|
| drawCompactEnrichedHeatmap(currentScenario);
|
|
|
|
|
| const canvas = document.getElementById("heatmap");
|
| const ctx = canvas.getContext("2d");
|
|
|
| ctx.font = "12px Arial";
|
| ctx.fillStyle = "#1976D2";
|
| ctx.textAlign = "center";
|
|
|
| switch(mode) {
|
| case "regularity":
|
| ctx.fillText("📊 Analyse de la régularité", canvas.width / 2, canvas.height - 10);
|
| break;
|
| case "effortPattern":
|
| ctx.fillText("🔄 Schéma d'effort", canvas.width / 2, canvas.height - 10);
|
| break;
|
| case "deadline":
|
| ctx.fillText("⏰ Gestion des échéances", canvas.width / 2, canvas.height - 10);
|
| break;
|
| case "combined":
|
| ctx.fillText("🎯 Vue combinée", canvas.width / 2, canvas.height - 10);
|
| break;
|
| }
|
| }
|
|
|
|
|
| window.changePersistenceAnalysis = changePersistenceAnalysis;
|
| window.updateStats = updateStats;
|
| window.showNotification = showNotification;
|
| window.fillSampleEvaluator = fillSampleEvaluator;
|
| window.clearEvaluatorFields = clearEvaluatorFields;
|
| </script>
|
|
|
| </body>
|
| </html> |