secutorpro's picture
🐳 14/07 - 01:18 - cree une page 🧠 Maillage Inversé Cognitif et une autres 🧠 Maillage seo/gepo Cognitif
6b47f67 verified
Raw
History Blame Contribute Delete
64.5 kB
<!DOCTYPE html>
<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 !important; }
}
</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>