TrueVision / templates /detect.html
HyperMehfin's picture
Upload 10 files
728527b verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="theme-color" content="#0a192f">
<title>DeepFake Detection - Video Analysis</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{{ url_for('static', filename='index.css') }}">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
/* Base styles */
:root {
--primary-color: #64ffda;
--primary-dark: #4cd6b3;
--bg-dark: #1a1a1a;
--bg-darker: #111d40;
--text-light: #8892b0;
--border-color: rgba(100, 255, 218, 0.1);
}
/* Navigation */
.navbar {
background: var(--bg-dark);
padding: 1rem 2rem;
height: 70px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
position: sticky;
top: 0;
z-index: 1000;
}
.navbar-brand {
color: var(--primary-color);
font-size: 1.5rem;
font-weight: bold;
text-decoration: none;
transition: color 0.3s ease;
}
.navbar-brand:hover {
color: var(--primary-dark);
}
/* Hamburger Button (Hidden on PC) */
.hamburger {
display: none;
background: none;
border: none;
color: #64ffda;
font-size: 2rem;
cursor: pointer;
padding: 0;
}
.navbar-nav {
display: flex;
gap: 1rem;
align-items: center;
transition: all 0.3s ease;
}
.nav-link {
color: #fff;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 4px;
transition: all 0.3s ease;
}
.nav-link:hover, .nav-link.active {
background: rgba(100, 255, 218, 0.1);
color: var(--primary-color);
}
.nav-link.highlight {
background: var(--primary-color);
color: var(--bg-dark);
}
.nav-link.highlight:hover {
background: var(--primary-dark);
}
/* Content */
.content {
padding: 2rem;
max-width: 1200px;
margin: 0 auto;
animation: fadeIn 0.5s ease-in-out;
}
/* Upload Section */
.upload-section { margin: 2rem 0; }
.upload-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
padding: 2rem;
}
.file-input-wrapper {
position: relative;
width: 100%;
max-width: 400px;
}
.file-input-wrapper input[type="file"] {
position: absolute;
left: 0;
top: 0;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
.file-label {
display: block;
padding: 1rem 2rem;
background: rgba(100, 255, 218, 0.1);
border: 2px dashed var(--primary-color);
border-radius: 8px;
text-align: center;
color: var(--primary-color);
cursor: pointer;
transition: all 0.3s ease;
}
.file-label:hover {
background: rgba(100, 255, 218, 0.2);
transform: translateY(-2px);
}
/* Loading States */
.loading-container {
display: none;
flex-direction: column;
align-items: center;
gap: 1rem;
margin: 1rem 0;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(100, 255, 218, 0.1);
border-top: 3px solid var(--primary-color);
border-radius: 50%;
animation: spin 1s linear infinite;
}
.loading-text {
color: var(--primary-color);
font-size: 0.9rem;
}
/* Results Section */
.result-container {
background: var(--bg-darker);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
text-align: center;
}
.result-heading {
color: var(--primary-color);
font-size: 1.8rem;
margin-bottom: 1.5rem;
font-weight: 600;
}
.result-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
}
.result-text {
font-size: 3rem;
font-weight: bold;
margin: 1rem 0;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
letter-spacing: 2px;
}
.result-text.fake {
color: #ff4d4d;
background: linear-gradient(135deg, #ff4d4d, #ff6b6b);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.result-text.real {
color: #4dff4d;
background: linear-gradient(135deg, #4dff4d, #6bff6b);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.confidence-text {
font-size: 1.2rem;
color: var(--text-light);
margin-top: 0.5rem;
font-weight: 500;
}
/* Analysis Details */
.details-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin-top: 1rem;
}
.detail-item {
background: rgba(17, 34, 64, 0.3);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 1rem;
text-align: center;
}
.detail-label {
display: block;
color: var(--primary-color);
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.detail-value {
font-size: 1.5rem;
font-weight: 600;
color: var(--text-light);
}
/* Frames Grid */
.frames-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin: 2rem 0;
}
.frame-item {
position: relative;
background: rgba(17, 34, 64, 0.5);
border: 1px solid var(--border-color);
border-radius: 8px;
overflow: hidden;
transition: all 0.3s ease;
cursor: pointer;
}
.frame-item:hover {
transform: scale(1.05);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}
.frame-item img {
width: 100%;
height: 200px;
object-fit: cover;
display: block;
}
.frame-info {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 0.5rem;
background: rgba(17, 34, 64, 0.8);
text-align: center;
transform: translateY(100%);
transition: transform 0.3s ease;
}
.frame-item:hover .frame-info {
transform: translateY(0);
}
.frame-number {
color: var(--primary-color);
font-weight: 600;
margin: 0;
font-size: 0.9rem;
}
/* Footer */
.footer {
margin-top: auto;
padding: 3rem 0;
background: var(--bg-darker);
border-top: 1px solid var(--border-color);
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
display: flex;
justify-content: space-between;
gap: 2rem;
}
.footer-section { flex: 1; }
.footer-section h3 { color: var(--primary-color); margin-bottom: 1rem; }
.footer-link { color: var(--text-light); text-decoration: none; display: block; margin: 0.5rem 0; transition: color 0.3s ease; }
.footer-link:hover { color: var(--primary-color); }
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
.error-message {
color: #ff4d4d;
background: rgba(255, 77, 77, 0.1);
border: 1px solid #ff4d4d;
padding: 0.75rem;
border-radius: 4px;
margin: 1rem 0;
text-align: center;
}
.cta-button {
display: inline-block;
padding: 1rem 2rem;
background: var(--primary-color);
color: var(--bg-dark);
text-decoration: none;
border-radius: 4px;
font-weight: bold;
transition: all 0.3s ease;
border: none;
cursor: pointer;
}
.cta-button:hover {
background: var(--primary-dark);
transform: translateY(-2px);
}
/* Feature Cards */
.feature-card {
background: var(--bg-darker);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 2rem;
margin: 2rem 0;
}
.success-message { margin: 2rem 0; }
/* Pie Chart Styles */
.pie-chart-section {
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
padding: 2.5rem;
background: linear-gradient(135deg, rgba(100, 255, 218, 0.08) 0%, rgba(26, 26, 26, 0.9) 100%);
border: 1px solid rgba(100, 255, 218, 0.15);
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
.pie-chart-section h3 {
color: #64ffda;
margin: 0;
font-size: 1.8rem;
font-weight: 600;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}
.pie-chart-container {
position: relative;
width: 350px;
height: 350px;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
background: rgba(26, 26, 26, 0.3);
border-radius: 50%;
padding: 20px;
}
#resultPieChart {
position: relative;
width: 100%;
height: 100%;
border-radius: 50%;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
background: transparent;
}
.pie-chart-legend {
display: flex;
justify-content: center;
gap: 2.5rem;
margin-top: 1rem;
padding: 1.5rem;
background: rgba(26, 26, 26, 0.8);
border-radius: 12px;
border: 1px solid rgba(100, 255, 218, 0.15);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
width: 100%;
max-width: 400px;
}
.legend-item {
display: flex;
align-items: center;
gap: 1rem;
padding: 0.75rem 1.5rem;
border-radius: 8px;
transition: all 0.3s ease;
}
.legend-color {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 6px;
border: 2px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.real-color { background: linear-gradient(135deg, #27ae60, #2ecc71); }
.fake-color { background: linear-gradient(135deg, #e74c3c, #c0392b); }
.legend-text {
color: var(--text-light);
font-size: 1.1rem;
font-weight: 600;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
/* Heatmap Section Styles */
.heatmap-section {
background: var(--bg-darker);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
text-align: center;
}
.heatmap-container {
margin-top: 1.5rem;
display: flex;
justify-content: center;
align-items: center;
gap: 2rem;
flex-wrap: wrap;
}
.heatmap-image-wrapper {
position: relative;
max-width: 100%;
border-radius: 12px;
overflow: hidden;
border: 2px solid var(--primary-color);
box-shadow: 0 8px 32px rgba(0, 255, 218, 0.2);
}
.heatmap-image {
width: 100%;
display: block;
}
.heatmap-legend {
display: flex;
flex-direction: column;
gap: 1rem;
text-align: left;
background: rgba(17, 34, 64, 0.5);
padding: 1.5rem;
border-radius: 8px;
border: 1px solid var(--border-color);
}
.heatmap-legend-item { display: flex; align-items: center; gap: 0.75rem; }
.heatmap-color-scale {
width: 150px;
height: 12px;
background: linear-gradient(to right, #3b4cc0, #b40426);
border-radius: 6px;
}
.heatmap-info-text {
color: var(--text-light);
max-width: 500px;
margin: 1rem auto 0;
font-size: 0.95rem;
line-height: 1.6;
}
/* --- MOBILE HAMBURGER MENU & FIXES --- */
@media (max-width: 768px) {
body {
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
user-select: none;
}
.navbar {
padding: 1rem 1.5rem;
}
.hamburger {
display: block;
}
.navbar-nav {
display: flex;
flex-direction: column;
position: absolute;
top: 70px;
left: 0;
width: 100%;
background: rgba(17, 29, 64, 0.98);
padding: 0;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
max-height: 0;
overflow: hidden;
opacity: 0;
transition: all 0.3s ease;
}
.navbar-nav.active {
max-height: 500px;
padding: 1rem 0;
opacity: 1;
}
.nav-link {
width: 100%;
text-align: center;
padding: 1.2rem;
border-radius: 0;
}
.content { padding: 1rem; }
.result-content { grid-template-columns: 1fr; }
.details-grid { grid-template-columns: 1fr; }
.footer-content { flex-direction: column; text-align: center; }
/* FIXED CHART SIZE AND LEGEND OVERLAP */
.pie-chart-container {
width: 100% !important;
max-width: 250px !important;
height: 250px !important;
padding: 10px;
margin: 0 auto;
box-sizing: border-box;
}
#resultPieChart {
width: 100% !important;
height: 100% !important;
}
.pie-chart-legend {
flex-direction: column;
gap: 1rem;
padding: 1rem;
margin-top: 1.5rem;
}
.heatmap-container { flex-direction: column; }
.file-input-wrapper { width: 100%; box-sizing: border-box; }
.upload-container { padding: 1rem; }
}
</style>
</head>
<body>
{% if data %}
<script>
window.data = '{{ data | safe }}';
</script>
{% else %}
<script>
window.data = null;
</script>
{% endif %}
<div id="root">
<nav class="navbar">
<a href="{{ url_for('homepage') }}" class="navbar-brand">DeepFake Detection</a>
<button class="hamburger" id="hamburger-btn" aria-label="Toggle menu">
</button>
<div class="navbar-nav" id="nav-links">
{% if current_user.is_authenticated %}
<a href="{{ url_for('detect') }}" class="nav-link active">Upload Video</a>
<a href="{{ url_for('image_detect') }}" class="nav-link">Detect Image</a>
<a href="{{ url_for('history') }}" class="nav-link">History</a>
{% if current_user.is_admin %}
<a href="{{ url_for('admin') }}" class="nav-link">Admin</a>
{% endif %}
<a href="{{ url_for('logout') }}" class="nav-link">Logout</a>
{% else %}
<a href="{{ url_for('signup') }}" class="nav-link highlight">Sign Up</a>
{% endif %}
</div>
</nav>
<main class="content" role="main">
<h1 class="heading">Detect DeepFake Videos</h1>
<p class="para">Upload your video for AI-powered analysis to detect potential manipulation.</p>
<section class="upload-section" aria-labelledby="upload-heading">
<h2 id="upload-heading" class="visually-hidden">Video Upload</h2>
<form action="{{ url_for('detect') }}" method="post" enctype="multipart/form-data" class="feature-card"
id="upload-form">
<div class="upload-container">
<div class="file-input-wrapper">
<input type="file" name="video" accept="video/*" required id="video-input"
aria-label="Choose a video file to analyze">
<label for="video-input" class="file-label">Choose Video</label>
</div>
<div id="video-preview-container" style="display: none;" aria-live="polite">
<video id="video-preview" controls style="max-width: 100%; border-radius: 8px;">
Your browser does not support the video tag.
</video>
</div>
<div class="loading-container" style="display: none;">
<div class="loading-spinner"></div>
<p class="loading-text">Analyzing video...</p>
</div>
<div id="error-message" class="error-message" role="alert" style="display: none;"></div>
<button type="submit" class="cta-button" id="analyze-btn">Analyze Video</button>
</div>
<p class="upload-info">Supported formats: MP4, AVI, MOV (Max size: 100MB)</p>
</form>
</section>
<div id="results" style="display: none;" role="region" aria-label="Analysis Results">
<div class="result-container">
<h2 class="result-heading">Analysis Result</h2>
<div class="result-content">
<div class="result-text-container">
<p id="result-text" class="result-text" role="status" aria-live="polite"></p>
<p id="confidence-text" class="confidence-text" aria-live="polite"></p>
</div>
</div>
</div>
<div class="pie-chart-section feature-card">
<h3>Result Distribution</h3>
<div class="pie-chart-container">
<canvas id="resultPieChart" width="350" height="350"></canvas>
</div>
<div class="pie-chart-legend">
<div class="legend-item">
<span class="legend-color real-color"></span>
<span class="legend-text">Real</span>
</div>
<div class="legend-item">
<span class="legend-color fake-color"></span>
<span class="legend-text">Fake</span>
</div>
</div>
</div>
<div id="heatmap-section" class="heatmap-section feature-card" style="display: none;">
<h3 class="result-heading" style="font-size: 1.5rem;">AI Focus Analysis (Heatmap)</h3>
<div class="heatmap-container">
<div class="heatmap-image-wrapper">
<img id="heatmap-image" src="" alt="AI Focus Heatmap" class="heatmap-image">
</div>
<div class="heatmap-legend">
<div class="heatmap-legend-item">
<span style="color: var(--primary-color); font-weight: 600;">Attention Scale:</span>
</div>
<div class="heatmap-legend-item">
<span style="color: #4cd6b3; font-size: 0.8rem;">Low</span>
<div class="heatmap-color-scale"></div>
<span style="color: #ff4d4d; font-size: 0.8rem;">High</span>
</div>
<p style="color: var(--text-light); font-size: 0.85rem; margin-top: 0.5rem;">
Red areas indicate regions where the AI model detected signs of manipulation.
</p>
</div>
</div>
<p class="heatmap-info-text">
The heatmap above visualizes the confidence score of the AI model across the video frames.
Red areas indicate frames with high probability of manipulation, while blue areas indicate real
content.
</p>
</div>
<div class="analysis-details feature-card" id="details-section">
<h3>Analysis Details</h3>
<div class="details-grid">
<div class="detail-item">
<span class="detail-label">FRAMES ANALYZED</span>
<span id="frames-analyzed" class="detail-value" aria-live="polite">0</span>
</div>
<div class="detail-item">
<span class="detail-label">PROCESSING TIME</span>
<span id="processing-time" class="detail-value" aria-live="polite">0s</span>
</div>
<div class="detail-item">
<span class="detail-label">MODEL CONFIDENCE</span>
<span id="model-confidence" class="detail-value" aria-live="polite">0%</span>
</div>
</div>
</div>
<div id="frames-section" class="feature-card" style="display: none;">
<h3 style="color: var(--primary-color); text-align: center; margin-bottom: 0.5rem;">Analyzed Frames
</h3>
<p style="color: var(--text-light); text-align: center; margin-bottom: 1.5rem; font-size: 0.9rem;">
Key frames extracted and analyzed for manipulation patterns
</p>
<div id="frames-grid" class="frames-container">
</div>
</div>
</div>
</main>
<footer class="footer" role="contentinfo">
<div class="footer-content">
<div class="footer-section">
<h3>About Us</h3>
<p>We are dedicated to detecting and preventing deepfake videos using advanced AI technology.</p>
</div>
<div class="footer-section">
<h3>Contact</h3>
<a href="mailto:contact@deepfakedetect.ai" class="footer-link">contact@deepfakedetect.ai</a>
<a href="https://github.com/deepfake-detect" target="_blank" rel="noopener noreferrer"
class="footer-link">GitHub</a>
</div>
<div class="footer-section">
<h3>Legal</h3>
<a href="{{ url_for('privacy') }}" class="footer-link">Privacy Policy</a>
<a href="{{ url_for('terms') }}" class="footer-link">Terms of Service</a>
<p>© 2025 DeepFake Detection</p>
</div>
</div>
</footer>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const hamburgerBtn = document.getElementById('hamburger-btn');
const navLinks = document.getElementById('nav-links');
hamburgerBtn.addEventListener('click', () => {
navLinks.classList.toggle('active');
});
document.querySelectorAll('.nav-link').forEach(link => {
link.addEventListener('click', () => {
navLinks.classList.remove('active');
});
});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const videoInput = document.getElementById('video-input');
const videoPreview = document.getElementById('video-preview');
const videoPreviewContainer = document.getElementById('video-preview-container');
const uploadForm = document.getElementById('upload-form');
const analyzeBtn = document.getElementById('analyze-btn');
const loadingContainer = document.querySelector('.loading-container');
const errorMessage = document.getElementById('error-message');
videoInput?.addEventListener('change', function () {
errorMessage.style.display = 'none';
if (this.files && this.files[0]) {
const file = this.files[0];
if (file.size > 100 * 1024 * 1024) {
errorMessage.textContent = 'File size exceeds 100MB limit';
errorMessage.style.display = 'block';
this.value = '';
videoPreviewContainer.style.display = 'none';
return;
}
const fileURL = URL.createObjectURL(file);
videoPreview.src = fileURL;
videoPreviewContainer.style.display = 'block';
const fileLabel = document.querySelector('.file-label');
fileLabel.textContent = file.name;
} else {
videoPreviewContainer.style.display = 'none';
videoPreview.src = '';
}
});
uploadForm?.addEventListener('submit', function (e) {
if (!videoInput.files || !videoInput.files[0]) {
e.preventDefault();
errorMessage.textContent = 'Please select a video file';
errorMessage.style.display = 'block';
return;
}
loadingContainer.style.display = 'flex';
analyzeBtn.disabled = true;
errorMessage.style.display = 'none';
});
const hasValidData = (
typeof window.data !== 'undefined' &&
window.data !== null &&
window.data !== '' &&
window.data !== 'null'
);
if (hasValidData) {
try {
const parsedData = typeof window.data === 'string' ? JSON.parse(window.data) : window.data;
if (!parsedData.output || !parsedData.confidence || !parsedData.processing_time) {
return;
}
const resultsDiv = document.getElementById('results');
const resultText = document.getElementById('result-text');
const confidenceText = document.getElementById('confidence-text');
const modelConfidence = document.getElementById('model-confidence');
const processingTime = document.getElementById('processing-time');
const pieChartCanvas = document.getElementById('resultPieChart');
const realColor = document.querySelector('.real-color');
const fakeColor = document.querySelector('.fake-color');
loadingContainer.style.display = 'none';
analyzeBtn.disabled = false;
resultsDiv.style.display = 'block';
resultText.textContent = parsedData.output;
resultText.className = `result-text ${parsedData.output.toLowerCase()}`;
confidenceText.textContent = `Confidence: ${parsedData.confidence.toFixed(2)}%`;
modelConfidence.textContent = `${parsedData.confidence.toFixed(2)}%`;
processingTime.textContent = `${parsedData.processing_time}s`;
const framesAnalyzed = document.getElementById('frames-analyzed');
if (framesAnalyzed) {
framesAnalyzed.textContent = parsedData.frames_analyzed || 0;
}
const heatmapSection = document.getElementById('heatmap-section');
const heatmapImage = document.getElementById('heatmap-image');
if (parsedData.heatmap_url) {
heatmapImage.src = '/' + parsedData.heatmap_url + '?t=' + new Date().getTime();
heatmapSection.style.display = 'block';
} else {
heatmapSection.style.display = 'none';
}
const framesSection = document.getElementById('frames-section');
const framesGrid = document.getElementById('frames-grid');
if (parsedData.frame_urls && parsedData.frame_urls.length > 0) {
framesGrid.innerHTML = '';
parsedData.frame_urls.forEach((frameUrl, index) => {
const frameItem = document.createElement('div');
frameItem.className = 'frame-item';
frameItem.innerHTML = `
<img src="/${frameUrl}?t=${new Date().getTime()}" alt="Frame ${index + 1}" loading="lazy">
<div class="frame-info">
<p class="frame-number">Frame ${index + 1}</p>
</div>
`;
framesGrid.appendChild(frameItem);
});
framesSection.style.display = 'block';
} else {
framesSection.style.display = 'none';
}
const successMessage = document.createElement('div');
successMessage.className = 'success-message';
successMessage.innerHTML = `
<div style="text-align: center; padding: 20px; background: linear-gradient(135deg, rgba(100, 255, 218, 0.1) 0%, rgba(26, 26, 26, 0.8) 100%); border-radius: 12px; margin: 20px 0; border: 1px solid rgba(100, 255, 218, 0.2);">
<h3 style="color: #64ffda; margin-bottom: 10px; font-size: 1.3rem;">✅ Analysis Complete!</h3>
<p style="color: #8892b0; margin: 0; font-size: 1rem;">Video processed successfully using advanced AI deep learning technology.</p>
</div>
`;
resultsDiv.insertBefore(successMessage, resultsDiv.firstChild);
const ctx = pieChartCanvas.getContext('2d');
const realPercentage = parsedData.output.toLowerCase() === 'real' ? parsedData.confidence : (100 - parsedData.confidence);
const fakePercentage = parsedData.output.toLowerCase() === 'fake' ? parsedData.confidence : (100 - parsedData.confidence);
if (window.resultChart) {
window.resultChart.destroy();
}
const chartData = [realPercentage, fakePercentage];
if (chartData.some(val => isNaN(val) || val < 0)) {
pieChartCanvas.style.display = 'none';
const fallbackDiv = document.createElement('div');
fallbackDiv.innerHTML = `
<div style="text-align: center; padding: 40px; color: #8892b0;">
<h4 style="color: #64ffda; margin-bottom: 20px;">Result Distribution</h4>
<div style="font-size: 2rem; font-weight: bold; color: ${parsedData.output.toLowerCase() === 'real' ? '#27ae60' : '#e74c3c'};">
${parsedData.output}
</div>
<div style="font-size: 1.2rem; margin-top: 10px;">
Confidence: ${parsedData.confidence.toFixed(1)}%
</div>
</div>
`;
pieChartCanvas.parentNode.appendChild(fallbackDiv);
return;
}
try {
window.resultChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Real', 'Fake'],
datasets: [{
data: chartData,
backgroundColor: ['#27ae60', '#e74c3c'],
borderWidth: 4,
borderColor: '#1a1a1a',
hoverBorderWidth: 6,
hoverBorderColor: '#64ffda'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
cutout: '65%',
plugins: {
legend: { display: false },
tooltip: {
enabled: true,
backgroundColor: 'rgba(26, 26, 26, 0.95)',
titleColor: '#64ffda',
bodyColor: '#8892b0',
borderColor: '#64ffda',
borderWidth: 2,
cornerRadius: 8,
displayColors: false,
callbacks: {
title: function (tooltipItems) { return tooltipItems[0].label; },
label: function (context) { return context.parsed.toFixed(1) + '%'; }
}
}
},
animation: {
animateRotate: true,
duration: 1500,
easing: 'easeInOutQuart'
},
elements: { arc: { borderWidth: 4 } }
}
});
} catch (chartError) {
pieChartCanvas.style.display = 'none';
const fallbackDiv = document.createElement('div');
fallbackDiv.innerHTML = `
<div style="text-align: center; padding: 40px; color: #8892b0;">
<h4 style="color: #64ffda; margin-bottom: 20px;">Result Distribution</h4>
<div style="font-size: 2rem; font-weight: bold; color: ${parsedData.output.toLowerCase() === 'real' ? '#27ae60' : '#e74c3c'};">
${parsedData.output}
</div>
<div style="font-size: 1.2rem; margin-top: 10px;">
Confidence: ${parsedData.confidence.toFixed(1)}%
</div>
</div>
`;
pieChartCanvas.parentNode.appendChild(fallbackDiv);
}
if (realColor && fakeColor) {
realColor.style.background = 'linear-gradient(135deg, #27ae60, #2ecc71)';
fakeColor.style.background = 'linear-gradient(135deg, #e74c3c, #c0392b)';
}
const legendTexts = document.querySelectorAll('.legend-text');
if (legendTexts.length >= 2) {
legendTexts[0].textContent = `Real (${realPercentage.toFixed(1)}%)`;
legendTexts[1].textContent = `Fake (${fakePercentage.toFixed(1)}%)`;
}
} catch (error) {
errorMessage.textContent = 'An error occurred while processing the results';
errorMessage.style.display = 'block';
}
}
});
</script>
</body>
</html>