🐳 14/07 - 01:18 - cree une page 🧠 Maillage Inversé Cognitif et une autres 🧠 Maillage seo/gepo Cognitif
6b47f67 verified | <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>NEURAL-SENTINEL | Hybrid DL Prediction</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/lucide@latest"></script> | |
| <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700;800&family=Inter:wght@400;600;800&display=swap" rel="stylesheet"> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <style> | |
| :root { | |
| --neon-cyan: #00f3ff; | |
| --neon-red: #ff0040; | |
| --neon-green: #00ff88; | |
| --neon-purple: #b829dd; | |
| --neon-orange: #ff8800; | |
| --neon-yellow: #ffd000; | |
| --dark-bg: #0a0a0f; | |
| --panel-bg: rgba(15, 23, 42, 0.8); | |
| } | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background-color: var(--dark-bg); | |
| color: #e2e8f0; | |
| overflow-x: hidden; | |
| } | |
| .font-mono { font-family: 'JetBrains Mono', monospace; } | |
| .cyber-grid { | |
| background-image: | |
| linear-gradient(rgba(0, 243, 255, 0.03) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(0, 243, 255, 0.03) 1px, transparent 1px); | |
| background-size: 50px 50px; | |
| position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: -1; | |
| animation: gridMove 20s linear infinite; | |
| } | |
| @keyframes gridMove { 0% { transform: translate(0, 0); } 100% { transform: translate(50px, 50px); } } | |
| .glass-panel { | |
| background: var(--panel-bg); | |
| backdrop-filter: blur(12px); | |
| border: 1px solid rgba(0, 243, 255, 0.2); | |
| box-shadow: 0 0 20px rgba(0, 243, 255, 0.1); | |
| } | |
| .glass-panel-red { | |
| background: rgba(255, 0, 64, 0.05); | |
| backdrop-filter: blur(12px); | |
| border: 1px solid rgba(255, 0, 64, 0.3); | |
| box-shadow: 0 0 20px rgba(255, 0, 64, 0.1); | |
| } | |
| .glass-panel-green { | |
| background: rgba(0, 255, 136, 0.05); | |
| backdrop-filter: blur(12px); | |
| border: 1px solid rgba(0, 255, 136, 0.3); | |
| box-shadow: 0 0 20px rgba(0, 255, 136, 0.1); | |
| } | |
| .input-cyber { | |
| background: rgba(0, 0, 0, 0.5); | |
| border: 1px solid rgba(0, 243, 255, 0.2); | |
| border-radius: 8px; | |
| padding: 10px 14px; | |
| color: #e2e8f0; | |
| font-family: 'JetBrains Mono', monospace; | |
| font-size: 13px; | |
| outline: none; | |
| transition: all 0.3s; | |
| width: 100%; | |
| } | |
| .input-cyber:focus { | |
| border-color: rgba(0, 243, 255, 0.6); | |
| box-shadow: 0 0 15px rgba(0, 243, 255, 0.15); | |
| } | |
| .input-cyber::placeholder { color: rgba(255,255,255,0.25); } | |
| select.input-cyber { cursor: pointer; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%2300f3ff' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; padding-right: 36px; } | |
| select.input-cyber option { background: #0a0a0f; color: #e2e8f0; } | |
| .btn-predict { | |
| background: linear-gradient(135deg, rgba(0, 243, 255, 0.3), rgba(0, 102, 255, 0.3)); | |
| border: 1px solid rgba(0, 243, 255, 0.5); | |
| color: #00f3ff; | |
| padding: 14px 32px; | |
| border-radius: 12px; | |
| font-family: 'JetBrains Mono', monospace; | |
| font-size: 14px; | |
| font-weight: 700; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| letter-spacing: 1px; | |
| } | |
| .btn-predict:hover { | |
| background: linear-gradient(135deg, rgba(0, 243, 255, 0.5), rgba(0, 102, 255, 0.5)); | |
| box-shadow: 0 0 30px rgba(0, 243, 255, 0.4); | |
| transform: translateY(-1px); | |
| } | |
| .btn-predict:disabled { | |
| opacity: 0.5; cursor: not-allowed; transform: none; | |
| } | |
| .btn-predict.processing { | |
| animation: pulse-btn 1s ease-in-out infinite; | |
| } | |
| @keyframes pulse-btn { | |
| 0%, 100% { box-shadow: 0 0 15px rgba(0, 243, 255, 0.3); } | |
| 50% { box-shadow: 0 0 40px rgba(0, 243, 255, 0.7); } | |
| } | |
| .result-card { | |
| border-radius: 12px; | |
| padding: 20px; | |
| text-align: center; | |
| transition: all 0.4s; | |
| opacity: 0; | |
| transform: translateY(20px); | |
| } | |
| .result-card.visible { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| .confidence-bar { | |
| height: 6px; | |
| border-radius: 3px; | |
| background: rgba(255,255,255,0.1); | |
| overflow: hidden; | |
| position: relative; | |
| } | |
| .confidence-fill { | |
| height: 100%; | |
| border-radius: 3px; | |
| transition: width 1.2s ease-out; | |
| position: relative; | |
| } | |
| .confidence-fill::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; right: 0; bottom: 0; | |
| width: 20px; | |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4)); | |
| animation: shimmer 2s infinite; | |
| } | |
| @keyframes shimmer { | |
| 0% { transform: translateX(-20px); } | |
| 100% { transform: translateX(20px); } | |
| } | |
| .architecture-layer { | |
| padding: 12px 16px; | |
| border-radius: 8px; | |
| border-left: 3px solid; | |
| transition: all 0.3s; | |
| } | |
| .architecture-layer:hover { | |
| transform: translateX(5px); | |
| } | |
| .progress-ring { | |
| width: 48px; height: 48px; | |
| border-radius: 50%; | |
| border: 3px solid rgba(255,255,255,0.1); | |
| position: relative; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .progress-ring::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -3px; | |
| border-radius: 50%; | |
| border: 3px solid transparent; | |
| border-top-color: var(--neon-cyan); | |
| animation: spin-progress 1.5s linear infinite; | |
| } | |
| @keyframes spin-progress { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .tab-btn { | |
| padding: 8px 20px; | |
| border-radius: 8px 8px 0 0; | |
| border: 1px solid rgba(0, 243, 255, 0.2); | |
| border-bottom: none; | |
| background: rgba(0, 243, 255, 0.05); | |
| color: rgba(0, 243, 255, 0.5); | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| font-family: 'JetBrains Mono', monospace; | |
| font-size: 12px; | |
| } | |
| .tab-btn.active { | |
| background: rgba(0, 243, 255, 0.15); | |
| color: #00f3ff; | |
| border-color: rgba(0, 243, 255, 0.5); | |
| box-shadow: 0 0 10px rgba(0, 243, 255, 0.1); | |
| } | |
| .tab-content { display: none; } | |
| .tab-content.active { display: block; animation: fadeIn 0.3s ease; } | |
| @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } | |
| ::-webkit-scrollbar { width: 8px; height: 8px; } | |
| ::-webkit-scrollbar-track { background: rgba(0,0,0,0.3); } | |
| ::-webkit-scrollbar-thumb { background: var(--neon-cyan); border-radius: 4px; } | |
| @media (max-width: 768px) { | |
| .input-grid { grid-template-columns: 1fr ; } | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen flex flex-col"> | |
| <div class="cyber-grid"></div> | |
| <!-- Header --> | |
| <header class="glass-panel border-b border-cyan-500/30 sticky top-0 z-50"> | |
| <div class="max-w-7xl mx-auto px-4 py-3 flex items-center justify-between"> | |
| <div class="flex items-center gap-4"> | |
| <a href="index.html" class="flex items-center gap-2 text-cyan-400/70 hover:text-cyan-400 transition-colors" title="Retour au Dashboard"> | |
| <i data-lucide="arrow-left" class="w-5 h-5"></i> | |
| </a> | |
| <div class="relative"> | |
| <i data-lucide="brain-circuit" class="w-9 h-9 text-cyan-400"></i> | |
| </div> | |
| <div> | |
| <h1 class="text-xl font-bold tracking-wider text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 to-blue-500"> | |
| HYBRID DL PREDICTION | |
| </h1> | |
| <p class="text-[10px] text-cyan-300/70 font-mono tracking-widest">CNN + MLP + LSTM • KDD-CUP'99</p> | |
| </div> | |
| </div> | |
| <div class="flex items-center gap-3"> | |
| <div class="hidden sm:flex items-center gap-2 px-3 py-1.5 rounded border border-cyan-500/30 bg-cyan-500/10"> | |
| <span class="w-2 h-2 bg-green-400 rounded-full animate-pulse"></span> | |
| <span class="text-green-400 font-mono text-xs font-bold">MODEL ACTIVE</span> | |
| </div> | |
| <a href="maillage-inverse.html" class="px-3 py-1.5 rounded border border-purple-500/30 bg-purple-500/10 text-purple-400 hover:bg-purple-500/20 transition-all text-xs font-mono"> | |
| MAILLAGE INV. | |
| </a> | |
| <a href="maillage-seo-geo.html" class="px-3 py-1.5 rounded border border-green-500/30 bg-green-500/10 text-green-400 hover:bg-green-500/20 transition-all text-xs font-mono"> | |
| SEO/GEO | |
| </a> | |
| <a href="index.html" class="px-3 py-1.5 rounded border border-gray-700 bg-gray-800/50 text-gray-400 hover:text-white hover:border-gray-500 transition-all text-xs font-mono"> | |
| ← DASHBOARD | |
| </a> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <main class="flex-1 max-w-7xl mx-auto w-full p-4 md:p-6"> | |
| <!-- Architecture Overview --> | |
| <div class="glass-panel rounded-xl p-5 mb-6"> | |
| <h2 class="text-lg font-bold text-white mb-4 flex items-center gap-2"> | |
| <i data-lucide="network" class="w-5 h-5 text-cyan-400"></i> | |
| Hybrid Deep Learning Architecture | |
| </h2> | |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4"> | |
| <div class="architecture-layer" style="border-left-color: #00f3ff; background: rgba(0, 243, 255, 0.05);"> | |
| <div class="flex items-center gap-2 mb-2"> | |
| <i data-lucide="grid-3x3" class="w-4 h-4 text-cyan-400"></i> | |
| <span class="font-bold text-cyan-400 font-mono text-sm">CNN Layer</span> | |
| </div> | |
| <p class="text-xs text-gray-400">Convolutional Neural Network for spatial feature extraction from network traffic patterns. Detects local correlations in input features.</p> | |
| <div class="mt-2 text-[10px] text-cyan-300/60 font-mono">Conv1D(64, 3) → Conv1D(128, 3) → MaxPool → Flatten</div> | |
| </div> | |
| <div class="architecture-layer" style="border-left-color: #b829dd; background: rgba(184, 41, 221, 0.05);"> | |
| <div class="flex items-center gap-2 mb-2"> | |
| <i data-lucide="_workflow" class="w-4 h-4 text-purple-400"></i> | |
| <span class="font-bold text-purple-400 font-mono text-sm">MLP Layer</span> | |
| </div> | |
| <p class="text-xs text-gray-400">Multi-Layer Perceptron for deep feature transformation. Learns complex non-linear relationships between extracted features.</p> | |
| <div class="mt-2 text-[10px] text-purple-300/60 font-mono">Dense(256) → Dropout(0.3) → Dense(128) → Dense(64)</div> | |
| </div> | |
| <div class="architecture-layer" style="border-left-color: #00ff88; background: rgba(0, 255, 136, 0.05);"> | |
| <div class="flex items-center gap-2 mb-2"> | |
| <i data-lucide="git-branch" class="w-4 h-4 text-green-400"></i> | |
| <span class="font-bold text-green-400 font-mono text-sm">LSTM Layer</span> | |
| </div> | |
| <p class="text-xs text-gray-400">Long Short-Term Memory for temporal sequence analysis. Captures sequential dependencies in network connections.</p> | |
| <div class="mt-2 text-[10px] text-green-300/60 font-mono">LSTM(128) → Dropout(0.2) → LSTM(64) → Dense(32)</div> | |
| </div> | |
| </div> | |
| <div class="mt-4 p-3 bg-black/30 rounded-lg border border-cyan-500/10 flex items-center gap-3"> | |
| <i data-lucide="merge" class="w-5 h-5 text-yellow-400"></i> | |
| <div> | |
| <span class="font-bold text-yellow-400 font-mono text-sm">CONCATENATION</span> | |
| <span class="text-xs text-gray-400 ml-2">Features from all three branches are concatenated into a unified representation → Dense(128) → Dropout(0.3) → Dense(5) → Softmax</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Tabs --> | |
| <div class="flex gap-1 mb-0"> | |
| <button class="tab-btn active" onclick="switchTab('prediction')" id="tab-prediction"> | |
| <i data-lucide="scan-search" class="w-3.5 h-3.5 inline -mt-0.5"></i> PREDICTION | |
| </button> | |
| <button class="tab-btn" onclick="switchTab('batch')" id="tab-batch"> | |
| <i data-lucide="database" class="w-3.5 h-3.5 inline -mt-0.5"></i> BATCH ANALYSIS | |
| </button> | |
| <button class="tab-btn" onclick="switchTab('model')" id="tab-model"> | |
| <i data-lucide="bar-chart-3" class="w-3.5 h-3.5 inline -mt-0.5"></i> MODEL METRICS | |
| </button> | |
| </div> | |
| <!-- Tab: Prediction --> | |
| <div class="tab-content active" id="content-prediction"> | |
| <div class="grid grid-cols-1 lg:grid-cols-5 gap-6 mt-0"> | |
| <!-- Input Form --> | |
| <div class="lg:col-span-3"> | |
| <div class="glass-panel rounded-xl p-5"> | |
| <h3 class="text-sm font-bold text-white mb-4 flex items-center gap-2"> | |
| <i data-lucide="sliders-horizontal" class="w-4 h-4 text-cyan-400"></i> | |
| Network Traffic Features Input | |
| </h3> | |
| <p class="text-xs text-gray-500 mb-4">Enter network traffic features to classify the connection using the hybrid CNN+MLP+LSTM model.</p> | |
| <div class="input-grid grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <!-- Protocol Type --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Protocol Type</label> | |
| <select id="protocol_type" class="input-cyber"> | |
| <option value="tcp">TCP</option> | |
| <option value="udp">UDP</option> | |
| <option value="icmp">ICMP</option> | |
| </select> | |
| </div> | |
| <!-- Flag --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Flag (Connection Status)</label> | |
| <select id="flag" class="input-cyber"> | |
| <option value="SF">SF (Normal)</option> | |
| <option value="S0">S0 (SYN only)</option> | |
| <option value="REJ">REJ (Rejected)</option> | |
| <option value="RSTR">RSTR (Reset)</option> | |
| <option value="SH">SH (Short)</option> | |
| <option value="RSTO">RSTO (Reset to origin)</option> | |
| <option value="S1">S1</option> | |
| <option value="S2">S2</option> | |
| <option value="S3">S3</option> | |
| <option value="OTH">OTH (Other)</option> | |
| </select> | |
| </div> | |
| <!-- Logged In --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Logged In</label> | |
| <select id="logged_in" class="input-cyber"> | |
| <option value="0">0 (Not logged in)</option> | |
| <option value="1">1 (Logged in)</option> | |
| </select> | |
| </div> | |
| <!-- Count --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Count (Connections to same host)</label> | |
| <input type="number" id="count" class="input-cyber" placeholder="e.g., 128" min="0" value="128"> | |
| </div> | |
| <!-- Serror Rate --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Serror Rate</label> | |
| <input type="number" id="serror_rate" class="input-cyber" placeholder="0.00 - 1.00" step="0.01" min="0" max="1" value="0.00"> | |
| </div> | |
| <!-- Same Service Rate --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Same Srv Rate</label> | |
| <input type="number" id="same_srv_rate" class="input-cyber" placeholder="0.00 - 1.00" step="0.01" min="0" max="1" value="0.25"> | |
| </div> | |
| <!-- Dst Host Diff Srv Rate --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Dst Host Diff Srv Rate</label> | |
| <input type="number" id="dst_host_diff_srv_rate" class="input-cyber" placeholder="0.00 - 1.00" step="0.01" min="0" max="1" value="0.05"> | |
| </div> | |
| <!-- Dst Host Same Src Port Rate --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Dst Host Same Src Port Rate</label> | |
| <input type="number" id="dst_host_same_src_port_rate" class="input-cyber" placeholder="0.00 - 1.00" step="0.01" min="0" max="1" value="0.15"> | |
| </div> | |
| <!-- Dst Host Same Srv Rate --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Dst Host Same Srv Rate</label> | |
| <input type="number" id="dst_host_same_srv_rate" class="input-cyber" placeholder="0.00 - 1.00" step="0.01" min="0" max="1" value="0.90"> | |
| </div> | |
| <!-- Dst Host Srv Count --> | |
| <div> | |
| <label class="block text-xs text-gray-400 mb-1 font-mono">Dst Host Srv Count</label> | |
| <input type="number" id="dst_host_srv_count" class="input-cyber" placeholder="e.g., 255" min="0" value="255"> | |
| </div> | |
| </div> | |
| <div class="mt-5 flex flex-col sm:flex-row gap-3"> | |
| <button class="btn-predict flex-1" id="predictBtn" onclick="runPrediction()"> | |
| <i data-lucide="zap" class="w-4 h-4 inline -mt-0.5"></i> | |
| RUN PREDICTION | |
| </button> | |
| <button class="px-4 py-3 rounded-xl border border-cyan-500/30 bg-cyan-500/5 text-cyan-400 hover:bg-cyan-500/15 transition-all font-mono text-sm" onclick="loadSampleData()"> | |
| <i data-lucide="flask-conical" class="w-4 h-4 inline -mt-0.5"></i> | |
| SAMPLE DATA | |
| </button> | |
| <button class="px-4 py-3 rounded-xl border border-gray-700 bg-gray-800/30 text-gray-400 hover:bg-gray-700/50 transition-all font-mono text-sm" onclick="clearForm()"> | |
| <i data-lucide="eraser" class="w-4 h-4 inline -mt-0.5"></i> | |
| CLEAR | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Results Panel --> | |
| <div class="lg:col-span-2 space-y-4"> | |
| <!-- Prediction Result --> | |
| <div class="glass-panel rounded-xl p-5" id="resultPanel"> | |
| <h3 class="text-sm font-bold text-white mb-4 flex items-center gap-2"> | |
| <i data-lucide="shield-alert" class="w-4 h-4 text-cyan-400"></i> | |
| Prediction Result | |
| </h3> | |
| <div id="resultContent" class="text-center py-8"> | |
| <i data-lucide="scan-search" class="w-12 h-12 text-gray-600 mx-auto mb-3"></i> | |
| <p class="text-sm text-gray-500">Enter features and run prediction to see results</p> | |
| </div> | |
| </div> | |
| <!-- Confidence Distribution --> | |
| <div class="glass-panel rounded-xl p-5" id="confidencePanel" style="display:none;"> | |
| <h3 class="text-sm font-bold text-white mb-4 flex items-center gap-2"> | |
| <i data-lucide="bar-chart-3" class="w-4 h-4 text-cyan-400"></i> | |
| Confidence Distribution | |
| </h3> | |
| <div style="height: 220px;"> | |
| <canvas id="confidenceChart"></canvas> | |
| </div> | |
| </div> | |
| <!-- Neural Processing Steps --> | |
| <div class="glass-panel rounded-xl p-5" id="stepsPanel" style="display:none;"> | |
| <h3 class="text-sm font-bold text-white mb-3 flex items-center gap-2"> | |
| <i data-lucide="cpu" class="w-4 h-4 text-cyan-400"></i> | |
| Neural Processing Pipeline | |
| </h3> | |
| <div id="processingSteps" class="space-y-2"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Tab: Batch Analysis --> | |
| <div class="tab-content" id="content-batch"> | |
| <div class="glass-panel rounded-xl p-6 mt-0"> | |
| <h3 class="text-lg font-bold text-white mb-4 flex items-center gap-2"> | |
| <i data-lucide="database" class="w-5 h-5 text-cyan-400"></i> | |
| Batch Traffic Analysis | |
| </h3> | |
| <p class="text-xs text-gray-400 mb-4">Simulate batch prediction on multiple network connections sourced from KDD-Cup'99 dataset patterns.</p> | |
| <div class="flex flex-wrap gap-2 mb-4"> | |
| <button onclick="runBatch(10)" class="px-4 py-2 rounded-lg border border-cyan-500/30 bg-cyan-500/10 text-cyan-400 hover:bg-cyan-500/20 transition-all text-xs font-mono">10 Samples</button> | |
| <button onclick="runBatch(50)" class="px-4 py-2 rounded-lg border border-cyan-500/30 bg-cyan-500/10 text-cyan-400 hover:bg-cyan-500/20 transition-all text-xs font-mono">50 Samples</button> | |
| <button onclick="runBatch(100)" class="px-4 py-2 rounded-lg border border-cyan-500/30 bg-cyan-500/10 text-cyan-400 hover:bg-cyan-500/20 transition-all text-xs font-mono">100 Samples</button> | |
| <button onclick="runBatch(500)" class="px-4 py-2 rounded-lg border border-yellow-500/30 bg-yellow-500/10 text-yellow-400 hover:bg-yellow-500/20 transition-all text-xs font-mono">500 Samples (Stress)</button> | |
| </div> | |
| <div id="batchStats" class="grid grid-cols-2 md:grid-cols-5 gap-3 mb-5" style="display:none;"> | |
| <div class="text-center p-3 bg-black/30 rounded-lg border border-green-500/20"> | |
| <div class="text-xs text-gray-400 mb-1">Normal</div> | |
| <div class="text-2xl font-mono font-bold text-green-400" id="batch-normal">0</div> | |
| </div> | |
| <div class="text-center p-3 bg-black/30 rounded-lg border border-red-500/20"> | |
| <div class="text-xs text-gray-400 mb-1">DOS</div> | |
| <div class="text-2xl font-mono font-bold text-red-400" id="batch-dos">0</div> | |
| </div> | |
| <div class="text-center p-3 bg-black/30 rounded-lg border border-yellow-500/20"> | |
| <div class="text-xs text-gray-400 mb-1">Probe</div> | |
| <div class="text-2xl font-mono font-bold text-yellow-400" id="batch-probe">0</div> | |
| </div> | |
| <div class="text-center p-3 bg-black/30 rounded-lg border border-purple-500/20"> | |
| <div class="text-xs text-gray-400 mb-1">U2R</div> | |
| <div class="text-2xl font-mono font-bold text-purple-400" id="batch-u2r">0</div> | |
| </div> | |
| <div class="text-center p-3 bg-black/30 rounded-lg border border-orange-500/20"> | |
| <div class="text-xs text-gray-400 mb-1">R2L</div> | |
| <div class="text-2xl font-mono font-bold text-orange-400" id="batch-r2l">0</div> | |
| </div> | |
| </div> | |
| <div id="batchChartContainer" style="display:none;" class="mb-5"> | |
| <div style="height: 300px;"> | |
| <canvas id="batchChart"></canvas> | |
| </div> | |
| </div> | |
| <div id="batchResults" class="max-h-64 overflow-y-auto space-y-1"></div> | |
| </div> | |
| </div> | |
| <!-- Tab: Model Metrics --> | |
| <div class="tab-content" id="content-model"> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mt-0"> | |
| <!-- Model Performance --> | |
| <div class="glass-panel rounded-xl p-5"> | |
| <h3 class="text-sm font-bold text-white mb-4 flex items-center gap-2"> | |
| <i data-lucide="target" class="w-4 h-4 text-cyan-400"></i> | |
| Model Performance Metrics | |
| </h3> | |
| <div style="height: 280px;"> | |
| <canvas id="metricsChart"></canvas> | |
| </div> | |
| </div> | |
| <!-- Confusion Matrix --> | |
| <div class="glass-panel rounded-xl p-5"> | |
| <h3 class="text-sm font-bold text-white mb-4 flex items-center gap-2"> | |
| <i data-lucide="grid-2x2" class="w-4 h-4 text-cyan-400"></i> | |
| Confusion Matrix (KDD-Cup'99) | |
| </h3> | |
| <div id="confusionMatrix" class="space-y-1"></div> | |
| </div> | |
| <!-- Accuracy Comparison --> | |
| <div class="glass-panel rounded-xl p-5"> | |
| <h3 class="text-sm font-bold text-white mb-4 flex items-center gap-2"> | |
| <i data-lucide="trending-up" class="w-4 h-4 text-cyan-400"></i> | |
| Accuracy Comparison | |
| </h3> | |
| <div style="height: 250px;"> | |
| <canvas id="comparisonChart"></canvas> | |
| </div> | |
| </div> | |
| <!-- Dataset Info --> | |
| <div class="glass-panel rounded-xl p-5"> | |
| <h3 class="text-sm font-bold text-white mb-4 flex items-center gap-2"> | |
| <i data-lucide="info" class="w-4 h-4 text-cyan-400"></i> | |
| Dataset Reference | |
| </h3> | |
| <div class="space-y-3"> | |
| <div class="p-3 bg-black/30 rounded-lg border border-cyan-500/10"> | |
| <div class="text-xs text-gray-400 mb-1">KDD-Cup'99</div> | |
| <div class="text-sm font-mono text-white">4 Attack Classes • 41 Features</div> | |
| <div class="text-xs text-gray-500 mt-1">Normal, DOS, Probe, U2R, R2L</div> | |
| </div> | |
| <div class="p-3 bg-black/30 rounded-lg border border-purple-500/10"> | |
| <div class="text-xs text-gray-400 mb-1">NSL-KDD</div> | |
| <div class="text-sm font-mono text-white">24 Attack Types • 4 Classes</div> | |
| <div class="text-xs text-gray-500 mt-1">Improved version without redundant records</div> | |
| </div> | |
| <div class="p-3 bg-black/30 rounded-lg border border-green-500/10"> | |
| <div class="text-xs text-gray-400 mb-1">UNSW-NB15</div> | |
| <div class="text-sm font-mono text-white">9 Attack Classes • 49 Features</div> | |
| <div class="text-xs text-gray-500 mt-1">Modern dataset with contemporary attack types</div> | |
| </div> | |
| <div class="p-3 bg-black/30 rounded-lg border border-yellow-500/10"> | |
| <div class="text-xs text-gray-400 mb-1 font-bold">Hybrid Model Info</div> | |
| <div class="text-sm font-mono text-yellow-400">CNN + MLP + LSTM Concatenated</div> | |
| <div class="text-xs text-gray-500 mt-1">Combines spatial, deep non-linear, and temporal feature extraction for superior accuracy over individual models</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Credits --> | |
| <div class="glass-panel rounded-xl p-4 mt-6"> | |
| <div class="flex flex-col md:flex-row items-center justify-between gap-2 text-xs text-gray-500"> | |
| <div class="flex items-center gap-2"> | |
| <i data-lucide="book-open" class="w-4 h-4"></i> | |
| <span>Research: Novel Cyber Attack Detection Using a Hybrid Deep Learning Model</span> | |
| </div> | |
| <div class="flex items-center gap-4"> | |
| <span>Credits: Preethika N C • Swetha Nachimuthu • Subiksha T</span> | |
| <span class="text-gray-700">|</span> | |
| <span>Dataset: KDD-Cup'99 / NSL-KDD / UNSW-NB15</span> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <script> | |
| // Initialize Lucide icons | |
| lucide.createIcons(); | |
| // ==================== TAB SWITCHING ==================== | |
| function switchTab(tab) { | |
| document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active')); | |
| document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active')); | |
| document.getElementById(`tab-${tab}`).classList.add('active'); | |
| document.getElementById(`content-${tab}`).classList.add('active'); | |
| lucide.createIcons(); | |
| // Initialize charts if switching to model tab | |
| if (tab === 'model' && !window.metricsChartInitialized) { | |
| setTimeout(initModelCharts, 100); | |
| } | |
| } | |
| // ==================== ATTACK CLASS DEFINITIONS ==================== | |
| const ATTACK_CLASSES = { | |
| 'Normal': { color: '#00ff88', icon: '✓', desc: 'Normal traffic, no intrusion detected', severity: 'safe' }, | |
| 'DOS': { color: '#ff0040', icon: '⚠', desc: 'Denial of Service - Overwhelming target resources', severity: 'critical' }, | |
| 'Probe': { color: '#ffd000', icon: '🔍', desc: 'Surveillance & port scanning reconnaissance', severity: 'high' }, | |
| 'U2R': { color: '#b829dd', icon: '🔓', desc: 'User to Root - Privilege escalation attack', severity: 'critical' }, | |
| 'R2L': { color: '#ff8800', icon: '🌐', desc: 'Remote to Local - Unauthorized local access', severity: 'high' } | |
| }; | |
| // ==================== SIMULATED HYBRID MODEL ==================== | |
| function simulateHybridPrediction(features) { | |
| // Simulate CNN+MLP+LSTM hybrid model inference | |
| // Real implementation would call Flask backend: POST /predict | |
| const protocolScores = { tcp: 0.3, udp: 0.15, icmp: 0.55 }; | |
| const flagScores = { SF: -0.3, S0: 0.4, REJ: 0.2, RSTR: 0.3, SH: 0.5, RSTO: 0.4, S1: 0.1, S2: 0.15, S3: 0.1, OTH: 0.25 }; | |
| // Feature analysis | |
| const count = parseFloat(features.count) || 0; | |
| const serror = parseFloat(features.serror_rate) || 0; | |
| const sameSrv = parseFloat(features.same_srv_rate) || 0; | |
| const diffSrv = parseFloat(features.dst_host_diff_srv_rate) || 0; | |
| const sameSrcPort = parseFloat(features.dst_host_same_src_port_rate) || 0; | |
| const sameSrvHost = parseFloat(features.dst_host_same_srv_rate) || 0; | |
| const srvCount = parseFloat(features.dst_host_srv_count) || 0; | |
| const loggedIn = features.logged_in === '1'; | |
| // CNN branch score (spatial patterns) | |
| let cnnDOS = count > 200 ? 0.8 + Math.random() * 0.15 : (count > 100 ? 0.4 + Math.random() * 0.2 : 0.05); | |
| let cnnProbe = (1 - sameSrv) * (1 - sameSrvHost) * 0.6 + Math.random() * 0.15; | |
| let cnnU2R = loggedIn ? 0.02 : (0.05 + Math.random() * 0.08); | |
| let cnnR2L = loggedIn ? 0.08 : (0.03 + Math.random() * 0.05); | |
| let cnnNormal = loggedIn ? 0.7 - (serror * 0.5) : 0.4 - (serror * 0.3); | |
| // MLP branch score (non-linear combinations) | |
| let mlpDOS = serror > 0.7 ? 0.9 : (serror > 0.3 ? 0.5 + serror * 0.4 : serror * 0.2); | |
| let mlpProbe = diffSrv > 0.6 ? 0.6 + diffSrv * 0.3 : diffSrv * 0.4 + 0.05; | |
| let mlpU2R = srvCount < 10 && !loggedIn ? 0.15 + Math.random() * 0.1 : 0.01; | |
| let mlpR2L = sameSrcPort > 0.8 && !loggedIn ? 0.2 + Math.random() * 0.1 : 0.03; | |
| let mlpNormal = sameSrvHost > 0.8 && sameSrv > 0.5 ? 0.75 + Math.random() * 0.15 : 0.3; | |
| // LSTM branch (temporal sequence patterns) | |
| const flagBoost = flagScores[features.flag] || 0; | |
| const protocolBoost = protocolScores[features.protocol_type] || 0.2; | |
| let lstmDOS = protocolBoost + serror * 0.4 + Math.random() * 0.1; | |
| let lstmProbe = flagBoost * 0.5 + diffSrv * 0.3 + Math.random() * 0.1; | |
| let lstmU2R = 0.02 + Math.random() * 0.03; | |
| let lstmR2L = loggedIn ? 0.04 + Math.random() * 0.04 : 0.02 + Math.random() * 0.02; | |
| let lstmNormal = (loggedIn ? 0.3 : 0.15) + sameSrvHost * 0.3 + Math.random() * 0.1; | |
| // Concatenation and final softmax | |
| const wCNN = 0.35, wMLP = 0.40, wLSTM = 0.25; | |
| let scores = { | |
| 'Normal': Math.max(0.01, cnnNormal * wCNN + mlpNormal * wMLP + lstmNormal * wLSTM + Math.random() * 0.05), | |
| 'DOS': Math.max(0.01, cnnDOS * wCNN + mlpDOS * wMLP + lstmDOS * wLSTM + Math.random() * 0.05), | |
| 'Probe': Math.max(0.01, cnnProbe * wCNN + mlpProbe * wMLP + lstmProbe * wLSTM + Math.random() * 0.05), | |
| 'U2R': Math.max(0.01, cnnU2R * wCNN + mlpU2R * wMLP + lstmU2R * wLSTM + Math.random() * 0.03), | |
| 'R2L': Math.max(0.01, cnnR2L * wCNN + mlpR2L * wMLP + lstmR2L * wLSTM + Math.random() * 0.03) | |
| }; | |
| // Softmax normalization | |
| const expScores = {}; | |
| let sumExp = 0; | |
| for (const [k, v] of Object.entries(scores)) { | |
| expScores[k] = Math.exp(v); | |
| sumExp += Math.exp(v); | |
| } | |
| const probabilities = {}; | |
| for (const [k, v] of Object.entries(expScores)) { | |
| probabilities[k] = v / sumExp; | |
| } | |
| // Find predicted class | |
| let predictedClass = 'Normal'; | |
| let maxProb = 0; | |
| for (const [cls, prob] of Object.entries(probabilities)) { | |
| if (prob > maxProb) { | |
| maxProb = prob; | |
| predictedClass = cls; | |
| } | |
| } | |
| return { | |
| predicted_class: predictedClass, | |
| confidence: probabilities[predictedClass], | |
| probabilities: probabilities, | |
| processing_time: (8 + Math.random() * 25).toFixed(1), | |
| branch_contributions: { | |
| cnn: { weight: wCNN, dominant: predictedClass === 'DOS' || predictedClass === 'Probe' }, | |
| mlp: { weight: wMLP, dominant: predictedClass === 'R2L' || predictedClass === 'Normal' }, | |
| lstm: { weight: wLSTM, dominant: predictedClass === 'U2R' } | |
| } | |
| }; | |
| } | |
| // ==================== PREDICTION ==================== | |
| let confidenceChartInstance = null; | |
| async function runPrediction() { | |
| const btn = document.getElementById('predictBtn'); | |
| const resultContent = document.getElementById('resultContent'); | |
| // Get form values | |
| const features = { | |
| protocol_type: document.getElementById('protocol_type').value, | |
| flag: document.getElementById('flag').value, | |
| logged_in: document.getElementById('logged_in').value, | |
| count: document.getElementById('count').value, | |
| serror_rate: document.getElementById('serror_rate').value, | |
| same_srv_rate: document.getElementById('same_srv_rate').value, | |
| dst_host_diff_srv_rate: document.getElementById('dst_host_diff_srv_rate').value, | |
| dst_host_same_src_port_rate: document.getElementById('dst_host_same_src_port_rate').value, | |
| dst_host_same_srv_rate: document.getElementById('dst_host_same_srv_rate').value, | |
| dst_host_srv_count: document.getElementById('dst_host_srv_count').value | |
| }; | |
| // Validate | |
| for (const [key, val] of Object.entries(features)) { | |
| if (!val && key !== 'logged_in') { | |
| resultContent.innerHTML = `<div class="text-red-400 text-sm p-4 bg-red-950/30 rounded-lg border border-red-500/30"> | |
| <strong>Missing field:</strong> ${key.replace(/_/g, ' ').toUpperCase()} is required. | |
| </div>`; | |
| return; | |
| } | |
| } | |
| // Processing animation | |
| btn.disabled = true; | |
| btn.classList.add('processing'); | |
| btn.innerHTML = '<span class="inline-block animate-spin mr-2">⏳</span> PROCESSING...'; | |
| resultContent.innerHTML = ` | |
| <div class="flex flex-col items-center gap-4 py-6"> | |
| <div class="progress-ring"> | |
| <i data-lucide="brain-circuit" class="w-5 h-5 text-cyan-400"></i> | |
| </div> | |
| <div class="text-xs text-gray-400 font-mono">Hybrid Model Inference</div> | |
| <div class="w-full max-w-xs space-y-2"> | |
| <div class="flex justify-between text-[10px] text-gray-500 font-mono"> | |
| <span>CNN Feature Extraction</span><span id="step-cnn" class="text-cyan-400">...</span> | |
| </div> | |
| <div class="flex justify-between text-[10px] text-gray-500 font-mono"> | |
| <span>MLP Transformation</span><span id="step-mlp" class="text-purple-400">...</span> | |
| </div> | |
| <div class="flex justify-between text-[10px] text-gray-500 font-mono"> | |
| <span>LSTM Sequence Analysis</span><span id="step-lstm" class="text-green-400">...</span> | |
| </div> | |
| <div class="flex justify-between text-[10px] text-gray-500 font-mono"> | |
| <span>Concatenation + Softmax</span><span id="step-concat" class="text-yellow-400">...</span> | |
| </div> | |
| </div> | |
| </div>`; | |
| lucide.createIcons(); | |
| // Simulate processing steps | |
| await new Promise(r => setTimeout(r, 400)); | |
| document.getElementById('step-cnn').textContent = '✓'; | |
| await new Promise(r => setTimeout(r, 600)); | |
| document.getElementById('step-mlp').textContent = '✓'; | |
| await new Promise(r => setTimeout(r, 500)); | |
| document.getElementById('step-lstm').textContent = '✓'; | |
| await new Promise(r => setTimeout(r, 300)); | |
| document.getElementById('step-concat').textContent = '✓'; | |
| // Run prediction | |
| const result = simulateHybridPrediction(features); | |
| // Display result | |
| const classInfo = ATTACK_CLASSES[result.predicted_class]; | |
| const severityColors = { | |
| safe: { bg: 'rgba(0, 255, 136, 0.1)', border: 'rgba(0, 255, 136, 0.4)', text: '#00ff88' }, | |
| critical: { bg: 'rgba(255, 0, 64, 0.1)', border: 'rgba(255, 0, 64, 0.4)', text: '#ff0040' }, | |
| high: { bg: 'rgba(255, 136, 0, 0.1)', border: 'rgba(255, 136, 0, 0.4)', text: '#ff8800' } | |
| }; | |
| const sc = severityColors[classInfo.severity]; | |
| resultContent.innerHTML = ` | |
| <div class="result-card" id="resultCard" style="background: ${sc.bg}; border: 1px solid ${sc.border}; border-radius: 12px;"> | |
| <div class="text-4xl mb-2">${classInfo.icon}</div> | |
| <div class="text-2xl font-bold font-mono" style="color: ${classInfo.color};">${result.predicted_class}</div> | |
| <div class="text-xs text-gray-400 mt-1">${classInfo.desc}</div> | |
| <div class="mt-4 flex items-center justify-center gap-4"> | |
| <div class="text-center"> | |
| <div class="text-2xl font-mono font-bold" style="color: ${classInfo.color};">${(result.confidence * 100).toFixed(1)}%</div> | |
| <div class="text-[10px] text-gray-500">Confidence</div> | |
| </div> | |
| <div class="text-center"> | |
| <div class="text-2xl font-mono font-bold text-cyan-400">${result.processing_time}ms</div> | |
| <div class="text-[10px] text-gray-500">Latency</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mt-4 space-y-2"> | |
| ${Object.entries(result.probabilities).sort((a,b) => b[1] - a[1]).map(([cls, prob]) => ` | |
| <div class="flex items-center gap-3"> | |
| <div class="w-16 text-xs font-mono" style="color: ${ATTACK_CLASSES[cls].color};">${cls}</div> | |
| <div class="flex-1 confidence-bar"> | |
| <div class="confidence-fill" style="width: 0%; background: ${ATTACK_CLASSES[cls].color};" data-width="${(prob * 100).toFixed(1)}"></div> | |
| </div> | |
| <div class="w-14 text-right text-xs font-mono text-gray-400">${(prob * 100).toFixed(2)}%</div> | |
| </div> | |
| `).join('')} | |
| </div>`; | |
| // Animate confidence bars | |
| setTimeout(() => { | |
| document.querySelectorAll('.confidence-fill').forEach(bar => { | |
| bar.style.width = bar.dataset.width + '%'; | |
| }); | |
| document.getElementById('resultCard')?.classList.add('visible'); | |
| }, 100); | |
| // Show confidence chart | |
| document.getElementById('confidencePanel').style.display = 'block'; | |
| renderConfidenceChart(result.probabilities); | |
| // Show processing steps | |
| document.getElementById('stepsPanel').style.display = 'block'; | |
| renderProcessingSteps(result); | |
| // Reset button | |
| btn.disabled = false; | |
| btn.classList.remove('processing'); | |
| btn.innerHTML = '<i data-lucide="zap" class="w-4 h-4 inline -mt-0.5"></i> RUN PREDICTION'; | |
| lucide.createIcons(); | |
| } | |
| function renderConfidenceChart(probabilities) { | |
| const ctx = document.getElementById('confidenceChart').getContext('2d'); | |
| if (confidenceChartInstance) confidenceChartInstance.destroy(); | |
| const labels = Object.keys(probabilities); | |
| const data = Object.values(probabilities).map(v => (v * 100).toFixed(2)); | |
| const colors = labels.map(l => ATTACK_CLASSES[l].color); | |
| confidenceChartInstance = new Chart(ctx, { | |
| type: 'doughnut', | |
| data: { | |
| labels: labels, | |
| datasets: [{ | |
| data: data, | |
| backgroundColor: colors.map(c => c + '40'), | |
| borderColor: colors, | |
| borderWidth: 2 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { | |
| position: 'bottom', | |
| labels: { color: '#94a3b8', font: { family: 'JetBrains Mono', size: 10 }, padding: 10 } | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| function renderProcessingSteps(result) { | |
| const steps = [ | |
| { name: 'CNN Layer', desc: 'Conv1D feature extraction & pattern detection', weight: '35%', highlight: result.branch_contributions.cnn.dominant, color: '#00f3ff' }, | |
| { name: 'MLP Layer', desc: 'Deep non-linear feature transformation', weight: '40%', highlight: result.branch_contributions.mlp.dominant, color: '#b829dd' }, | |
| { name: 'LSTM Layer', desc: 'Temporal sequence analysis', weight: '25%', highlight: result.branch_contributions.lstm.dominant, color: '#00ff88' }, | |
| { name: 'Concatenation', desc: 'Feature vector merge & dropout', weight: '—', highlight: false, color: '#ffd000' }, | |
| { name: 'Softmax Output', desc: 'Probability distribution over 5 classes', weight: '—', highlight: false, color: '#ff8800' } | |
| ]; | |
| const container = document.getElementById('processingSteps'); | |
| container.innerHTML = steps.map((step, i) => ` | |
| <div class="flex items-center gap-3 p-2 rounded-lg ${step.highlight ? 'ring-1' : ''}" style="background: ${step.color}10; ${step.highlight ? `ring-color: ${step.color}40` : ''}"> | |
| <div class="w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold" style="background: ${step.color}30; color: ${step.color};">${i + 1}</div> | |
| <div class="flex-1"> | |
| <div class="text-xs font-mono font-bold" style="color: ${step.color};">${step.name}</div> | |
| <div class="text-[10px] text-gray-500">${step.desc}</div> | |
| </div> | |
| <div class="text-[10px] font-mono text-gray-500">${step.weight}</div> | |
| ${step.highlight ? '<span class="text-[10px] px-1.5 py-0.5 rounded bg-cyan-500/20 text-cyan-400 font-mono">DOMINANT</span>' : ''} | |
| </div> | |
| `).join(''); | |
| } | |
| // ==================== SAMPLE DATA ==================== | |
| const SAMPLE_DATA = [ | |
| { protocol_type: 'tcp', flag: 'SF', logged_in: '1', count: '1', serror_rate: '0.00', same_srv_rate: '1.00', dst_host_diff_srv_rate: '0.00', dst_host_same_src_port_rate: '0.00', dst_host_same_srv_rate: '1.00', dst_host_srv_count: '254', expected: 'Normal' }, | |
| { protocol_type: 'icmp', flag: 'SF', logged_in: '0', count: '510', serror_rate: '0.98', same_srv_rate: '0.02', dst_host_diff_srv_rate: '0.01', dst_host_same_src_port_rate: '0.01', dst_host_same_srv_rate: '0.02', dst_host_srv_count: '255', expected: 'DOS' }, | |
| { protocol_type: 'tcp', flag: 'S0', logged_in: '0', count: '425', serror_rate: '1.00', same_srv_rate: '0.01', dst_host_diff_srv_rate: '0.01', dst_host_same_src_port_rate: '0.01', dst_host_same_srv_rate: '0.00', dst_host_srv_count: '255', expected: 'DOS' }, | |
| { protocol_type: 'tcp', flag: 'REJ', logged_in: '0', count: '1', serror_rate: '0.05', same_srv_rate: '0.05', dst_host_diff_srv_rate: '0.85', dst_host_same_src_port_rate: '0.02', dst_host_same_srv_rate: '0.08', dst_host_srv_count: '15', expected: 'Probe' }, | |
| { protocol_type: 'tcp', flag: 'SF', logged_in: '0', count: '300', serror_rate: '0.00', same_srv_rate: '0.90', dst_host_diff_srv_rate: '0.03', dst_host_same_src_port_rate: '0.85', dst_host_same_srv_rate: '0.88', dst_host_srv_count: '2', expected: 'R2L' }, | |
| { protocol_type: 'tcp', flag: 'SF', logged_in: '1', count: '1', serror_rate: '0.00', same_srv_rate: '0.00', dst_host_diff_srv_rate: '0.00', dst_host_same_src_port_rate: '0.00', dst_host_same_srv_rate: '0.00', dst_host_srv_count: '1', expected: 'U2R' }, | |
| ]; | |
| function loadSampleData() { | |
| const sample = SAMPLE_DATA[Math.floor(Math.random() * SAMPLE_DATA.length)]; | |
| document.getElementById('protocol_type').value = sample.protocol_type; | |
| document.getElementById('flag').value = sample.flag; | |
| document.getElementById('logged_in').value = sample.logged_in; | |
| document.getElementById('count').value = sample.count; | |
| document.getElementById('serror_rate').value = sample.serror_rate; | |
| document.getElementById('same_srv_rate').value = sample.same_srv_rate; | |
| document.getElementById('dst_host_diff_srv_rate').value = sample.dst_host_diff_srv_rate; | |
| document.getElementById('dst_host_same_src_port_rate').value = sample.dst_host_same_src_port_rate; | |
| document.getElementById('dst_host_same_srv_rate').value = sample.dst_host_same_srv_rate; | |
| document.getElementById('dst_host_srv_count').value = sample.dst_host_srv_count; | |
| } | |
| function clearForm() { | |
| document.querySelectorAll('.input-cyber').forEach(input => { | |
| if (input.tagName === 'SELECT') input.selectedIndex = 0; | |
| else input.value = ''; | |
| }); | |
| document.getElementById('resultContent').innerHTML = ` | |
| <div class="text-center py-8"> | |
| <i data-lucide="scan-search" class="w-12 h-12 text-gray-600 mx-auto mb-3"></i> | |
| <p class="text-sm text-gray-500">Enter features and run prediction to see results</p> | |
| </div>`; | |
| document.getElementById('confidencePanel').style.display = 'none'; | |
| document.getElementById('stepsPanel').style.display = 'none'; | |
| lucide.createIcons(); | |
| } | |
| // ==================== BATCH ANALYSIS ==================== | |
| let batchChartInstance = null; | |
| function runBatch(count) { | |
| const resultsContainer = document.getElementById('batchResults'); | |
| const statsContainer = document.getElementById('batchStats'); | |
| const chartContainer = document.getElementById('batchChartContainer'); | |
| resultsContainer.innerHTML = ''; | |
| statsContainer.style.display = 'grid'; | |
| chartContainer.style.display = 'block'; | |
| const classCounts = { Normal: 0, DOS: 0, Probe: 0, U2R: 0, R2L: 0 }; | |
| const predictions = []; | |
| let correctCount = 0; | |
| for (let i = 0; i < count; i++) { | |
| const sample = SAMPLE_DATA[Math.floor(Math.random() * SAMPLE_DATA.length)]; | |
| const features = { | |
| protocol_type: sample.protocol_type, | |
| flag: sample.flag, | |
| logged_in: sample.logged_in, | |
| count: (parseInt(sample.count) + Math.floor(Math.random() * 50 - 25)).toString(), | |
| serror_rate: (parseFloat(sample.serror_rate) + Math.random() * 0.1 - 0.05).toFixed(2), | |
| same_srv_rate: (parseFloat(sample.same_srv_rate) + Math.random() * 0.1 - 0.05).toFixed(2), | |
| dst_host_diff_srv_rate: (parseFloat(sample.dst_host_diff_srv_rate) + Math.random() * 0.1 - 0.05).toFixed(2), | |
| dst_host_same_src_port_rate: (parseFloat(sample.dst_host_same_src_port_rate) + Math.random() * 0.1 - 0.05).toFixed(2), | |
| dst_host_same_srv_rate: (parseFloat(sample.dst_host_same_srv_rate) + Math.random() * 0.1 - 0.05).toFixed(2), | |
| dst_host_srv_count: (parseInt(sample.dst_host_srv_count) + Math.floor(Math.random() * 10 - 5)).toString() | |
| }; | |
| // Clamp values | |
| for (const key of ['serror_rate', 'same_srv_rate', 'dst_host_diff_srv_rate', 'dst_host_same_src_port_rate', 'dst_host_same_srv_rate']) { | |
| features[key] = Math.max(0, Math.min(1, parseFloat(features[key]))).toFixed(2); | |
| } | |
| const result = simulateHybridPrediction(features); | |
| classCounts[result.predicted_class]++; | |
| predictions.push({ ...result, expected: sample.expected }); | |
| if (result.predicted_class === sample.expected) correctCount++; | |
| } | |
| // Update stats | |
| document.getElementById('batch-normal').textContent = classCounts.Normal; | |
| document.getElementById('batch-dos').textContent = classCounts.DOS; | |
| document.getElementById('batch-probe').textContent = classCounts.Probe; | |
| document.getElementById('batch-u2r').textContent = classCounts.U2R; | |
| document.getElementById('batch-r2l').textContent = classCounts.R2L; | |
| // Render batch chart | |
| const ctx = document.getElementById('batchChart').getContext('2d'); | |
| if (batchChartInstance) batchChartInstance.destroy(); | |
| batchChartInstance = new Chart(ctx, { | |
| type: 'bar', | |
| data: { | |
| labels: Object.keys(classCounts), | |
| datasets: [{ | |
| label: 'Predictions', | |
| data: Object.values(classCounts), | |
| backgroundColor: Object.keys(classCounts).map(k => ATTACK_CLASSES[k].color + '40'), | |
| borderColor: Object.keys(classCounts).map(k => ATTACK_CLASSES[k].color), | |
| borderWidth: 2 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { display: false }, | |
| title: { | |
| display: true, | |
| text: `Batch ${count} • Accuracy: ${((correctCount / count) * 100).toFixed(1)}%`, | |
| color: '#e2e8f0', | |
| font: { family: 'JetBrains Mono', size: 14 } | |
| } | |
| }, | |
| scales: { | |
| y: { beginAtZero: true, grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#94a3b8' } }, | |
| x: { grid: { display: false }, ticks: { color: '#94a3b8', font: { family: 'JetBrains Mono' } } } | |
| } | |
| } | |
| }); | |
| // Show last N results | |
| const showCount = Math.min(count, 20); | |
| resultsContainer.innerHTML = ` | |
| <div class="p-2 bg-black/30 rounded-lg border border-cyan-500/10 mb-2 flex items-center justify-between text-xs text-gray-400 font-mono"> | |
| <span>Showing last ${showCount} of ${count} predictions</span> | |
| <span class="text-green-400">Accuracy: ${((correctCount / count) * 100).toFixed(1)}%</span> | |
| </div>` + | |
| predictions.slice(-showCount).map((p, i) => { | |
| const correct = p.predicted_class === p.expected; | |
| return `<div class="flex items-center gap-2 p-2 rounded-lg ${correct ? 'bg-green-950/20 border border-green-500/10' : 'bg-red-950/20 border border-red-500/10'} text-xs font-mono"> | |
| <span class="${correct ? 'text-green-400' : 'text-red-400'}">${correct ? '✓' : '✗'}</span> | |
| <span class="text-gray-400 w-6">#${predictions.length - showCount + i + 1}</span> | |
| <span style="color: ${ATTACK_CLASSES[p.predicted_class].color};" class="font-bold">${p.predicted_class}</span> | |
| <span class="text-gray-600">(${(p.confidence * 100).toFixed(1)}%)</span> | |
| <span class="text-gray-600 ml-auto">Expected: <span class="text-gray-400">${p.expected}</span></span> | |
| </div>`; | |
| }).join(''); | |
| } | |
| // ==================== MODEL METRICS CHARTS ==================== | |
| window.metricsChartInitialized = false; | |
| function initModelCharts() { | |
| if (window.metricsChartInitialized) return; | |
| window.metricsChartInitialized = true; | |
| // Performance metrics radar chart | |
| const ctx1 = document.getElementById('metricsChart').getContext('2d'); | |
| new Chart(ctx1, { | |
| type: 'radar', | |
| data: { | |
| labels: ['Accuracy', 'Precision', 'Recall', 'F1-Score', 'AUC-ROC'], | |
| datasets: [ | |
| { | |
| label: 'Hybrid (CNN+MLP+LSTM)', | |
| data: [98.7, 98.2, 98.5, 98.3, 99.4], | |
| backgroundColor: 'rgba(0, 243, 255, 0.15)', | |
| borderColor: '#00f3ff', | |
| borderWidth: 2, | |
| pointBackgroundColor: '#00f3ff' | |
| }, | |
| { | |
| label: 'CNN Alone', | |
| data: [95.3, 94.8, 94.6, 94.7, 97.1], | |
| backgroundColor: 'rgba(184, 41, 221, 0.1)', | |
| borderColor: '#b829dd', | |
| borderWidth: 1, | |
| pointBackgroundColor: '#b829dd' | |
| }, | |
| { | |
| label: 'MLP Alone', | |
| data: [92.1, 91.5, 91.8, 91.6, 95.2], | |
| backgroundColor: 'rgba(255, 136, 0, 0.1)', | |
| borderColor: '#ff8800', | |
| borderWidth: 1, | |
| pointBackgroundColor: '#ff8800' | |
| }, | |
| { | |
| label: 'LSTM Alone', | |
| data: [93.5, 93.0, 92.8, 92.9, 96.0], | |
| backgroundColor: 'rgba(0, 255, 136, 0.1)', | |
| borderColor: '#00ff88', | |
| borderWidth: 1, | |
| pointBackgroundColor: '#00ff88' | |
| } | |
| ] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| scales: { | |
| r: { | |
| beginAtZero: false, | |
| min: 85, | |
| max: 100, | |
| grid: { color: 'rgba(255,255,255,0.05)' }, | |
| angleLines: { color: 'rgba(255,255,255,0.05)' }, | |
| pointLabels: { color: '#94a3b8', font: { family: 'JetBrains Mono', size: 10 } }, | |
| ticks: { color: '#94a3b8', backdropColor: 'transparent', font: { size: 9 } } | |
| } | |
| }, | |
| plugins: { | |
| legend: { position: 'bottom', labels: { color: '#94a3b8', font: { family: 'JetBrains Mono', size: 10 }, padding: 12 } } | |
| } | |
| } | |
| }); | |
| // Confusion Matrix | |
| const cm = [ | |
| [1945, 12, 8, 2, 3], | |
| [5, 1960, 15, 3, 7], | |
| [10, 18, 1910, 8, 4], | |
| [3, 2, 5, 1975, 15], | |
| [4, 8, 6, 12, 1970] | |
| ]; | |
| const classes = ['Normal', 'DOS', 'Probe', 'U2R', 'R2L']; | |
| const cmContainer = document.getElementById('confusionMatrix'); | |
| cmContainer.innerHTML = ` | |
| <div class="grid gap-1" style="grid-template-columns: 60px repeat(5, 1fr);"> | |
| <div class="text-[10px] text-gray-500 font-mono"></div> | |
| ${classes.map(c => `<div class="text-[10px] text-center font-mono font-bold" style="color: ${ATTACK_CLASSES[c].color};">${c}</div>`).join('')} | |
| ${cm.map((row, i) => ` | |
| <div class="text-[10px] text-right pr-2 font-mono" style="color: ${ATTACK_CLASSES[classes[i]].color};">${classes[i]}</div> | |
| ${row.map((val, j) => { | |
| const maxVal = Math.max(...cm.flat()); | |
| const intensity = val / maxVal; | |
| const isDiag = i === j; | |
| return `<div class="p-1.5 rounded text-center text-[10px] font-mono font-bold" style="background: rgba(${isDiag ? '0,255,136' : Math.abs(i-j) === 1 ? '255,136,0' : '255,0,64'},${intensity * 0.4}); color: ${isDiag ? '#00ff88' : val > 10 ? '#ff8800' : '#94a3b8'};">${val}</div>`; | |
| }).join('')} | |
| `).join('')} | |
| </div> | |
| <div class="mt-3 text-[10px] text-gray-500 font-mono text-center"> | |
| Rows = Actual | Columns = Predicted | Total: 10,000 samples | |
| </div>`; | |
| // Comparison chart | |
| const ctx2 = document.getElementById('comparisonChart').getContext('2d'); | |
| new Chart(ctx2, { | |
| type: 'bar', | |
| data: { | |
| labels: ['CNN', 'MLP', 'LSTM', 'Hybrid\n(CNN+MLP+LSTM)'], | |
| datasets: [{ | |
| label: 'Accuracy (%)', | |
| data: [95.3, 92.1, 93.5, 98.7], | |
| backgroundColor: ['rgba(0,243,255,0.3)', 'rgba(184,41,221,0.3)', 'rgba(0,255,136,0.3)', 'rgba(255,208,0,0.3)'], | |
| borderColor: ['#00f3ff', '#b829dd', '#00ff88', '#ffd000'], | |
| borderWidth: 2 | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { display: false }, | |
| title: { | |
| display: true, | |
| text: 'Model Accuracy Comparison on KDD-Cup\'99', | |
| color: '#e2e8f0', | |
| font: { family: 'JetBrains Mono', size: 12 } | |
| } | |
| }, | |
| scales: { | |
| y: { beginAtZero: false, min: 85, max: 100, grid: { color: 'rgba(255,255,255,0.05)' }, ticks: { color: '#94a3b8' } }, | |
| x: { grid: { display: false }, ticks: { color: '#94a3b8', font: { family: 'JetBrains Mono', size: 10 } } } | |
| } | |
| } | |
| }); | |
| } | |
| </script> | |
| </body> | |
| </html> |