import { useState, useEffect, useRef } from 'react'; import * as THREE from 'three'; function NeuralNetworkDiagram({ width = 420, height = 280 }) { const [hovered, setHovered] = useState(null); const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 80); return () => clearInterval(id); }, []); const layers = [ { x: 60, nodes: [80, 130, 180, 230], label: 'لایه ورودی' }, { x: 160, nodes: [100, 155, 210], label: 'لایه پنهان ۱' }, { x: 260, nodes: [110, 165, 220], label: 'لایه توجه' }, { x: 360, nodes: [140, 195], label: 'خروجی مدل' }, ]; const pulses = []; for (let li = 0; li < layers.length - 1; li++) { const from = layers[li], to = layers[li + 1]; from.nodes.forEach((fy, fi) => { to.nodes.forEach((ty, ti) => { const phase = (tick + li * 7 + fi * 3 + ti * 5) % 40; if (phase < 20) pulses.push({ x: from.x + (to.x - from.x) * phase / 20, y: fy + (ty - fy) * phase / 20 }); }); }); } const nodeColors = ['#0F6B73', '#D49A2A', '#C76D4A', '#2F8F6B']; return ( ); } function DataPipelineDiagram({ compact = false }) { const [tick, setTick] = useState(0); const [hovered, setHovered] = useState(null); useEffect(() => { const id = setInterval(() => setTick(t => (t + 1) % 100), 60); return () => clearInterval(id); }, []); const steps = [ { id: 'raw', label: 'داده خام', icon: '⬡', color: '#5F6B6D', desc: 'جمعآوری از منابع مختلف' }, { id: 'clean', label: 'پاکسازی', icon: '◈', color: '#D49A2A', desc: 'حذف تکراری و نویز' }, { id: 'label', label: 'برچسبگذاری', icon: '◉', color: '#C76D4A', desc: 'دستهبندی و تعریف' }, { id: 'feature', label: 'ویژگیسازی', icon: '⬟', color: '#0F6B73', desc: 'استخراج ویژگی' }, { id: 'train', label: 'آموزش مدل', icon: '◈', color: '#2F8F6B', desc: 'یادگیری از داده' }, { id: 'eval', label: 'ارزیابی', icon: '◉', color: '#D49A2A', desc: 'سنجش عملکرد' }, { id: 'output', label: 'خروجی', icon: '★', color: '#0F6B73', desc: 'مدل آماده' }, ]; const W = compact ? 480 : 700, H = compact ? 140 : 180; const stepW = W / steps.length; return ( ); } function CyberSecurityDiagram() { const [hovered, setHovered] = useState(null); const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 100); return () => clearInterval(id); }, []); const cx = 200, cy = 150, r = 90; const threats = [ { angle: 0, label: 'فیشینگ', color: '#C94C4C' }, { angle: 60, label: 'حمله زنجیره تأمین', color: '#D08A22' }, { angle: 120, label: 'آسیبپذیری کتابخانه', color: '#C76D4A' }, { angle: 180, label: 'دسترسی غیرمجاز', color: '#C94C4C' }, { angle: 240, label: 'باجافزار', color: '#D08A22' }, { angle: 300, label: 'حمله DDoS', color: '#C76D4A' }, ]; return ( ); } function StartupGrowthDiagram() { const [progress, setProgress] = useState(0); useEffect(() => { let v = 0; const id = setInterval(() => { v = Math.min(v + 2, 100); setProgress(v); if (v >= 100) clearInterval(id); }, 20); return () => clearInterval(id); }, []); const milestones = ['ایده', 'محصول اولیه', 'جذب کاربر', 'درآمد', 'مقیاسپذیری']; const W = 400, H = 200, padX = 40, padY = 20; const points = milestones.map((_, i) => { const t = i / (milestones.length - 1); return { x: padX + t * (W - padX * 2), y: H - padY - Math.pow(t, 1.8) * (H - padY * 3) }; }); const drawProgress = Math.min(progress / 100, 1); const pathPoints = points.filter((_, i) => i / (milestones.length - 1) <= drawProgress + 0.01); const pathD = pathPoints.length > 1 ? pathPoints.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`).join(' ') : ''; return ( ); } function HardwareChipDiagram() { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 70); return () => clearInterval(id); }, []); const blocks = [ { x: 30, y: 60, w: 80, h: 40, label: 'حافظه', color: '#D49A2A' }, { x: 160, y: 40, w: 80, h: 80, label: 'پردازنده', color: '#0F6B73' }, { x: 290, y: 60, w: 80, h: 40, label: 'شتابدهنده AI', color: '#C76D4A' }, { x: 30, y: 150, w: 80, h: 40, label: 'گذرگاه داده', color: '#2F8F6B' }, { x: 290, y: 150, w: 80, h: 40, label: 'کنترلر حافظه', color: '#5F6B6D' }, ]; const routes = [ { x1: 110, y1: 80, x2: 160, y2: 80 }, { x1: 240, y1: 80, x2: 290, y2: 80 }, { x1: 110, y1: 170, x2: 160, y2: 120 }, { x1: 240, y1: 100, x2: 290, y2: 170 }, { x1: 200, y1: 120, x2: 200, y2: 170 }, ]; return ( ); } function FutureTimelineDiagram() { const [activeIdx, setActiveIdx] = useState(null); const milestones = [ { year: '۲۰۲۵', label: 'AGI اولیه', color: '#0F6B73' }, { year: '۲۰۲۷', label: 'رایانش کوانتومی', color: '#D49A2A' }, { year: '۲۰۲۹', label: 'رباتیک خودکار', color: '#C76D4A' }, { year: '۲۰۳۱', label: 'رابط مغز-ماشین', color: '#2F8F6B' }, { year: '۲۰۳۵', label: 'جوش هستهای تجاری', color: '#0F6B73' }, ]; const W = 480, H = 120; return ( ); } function SoftwareArchDiagram() { const modules = [ { x: 180, y: 30, label: 'API Gateway', color: '#0F6B73' }, { x: 60, y: 110, label: 'Auth Service', color: '#2F8F6B' }, { x: 180, y: 110, label: 'Core Service', color: '#D49A2A' }, { x: 300, y: 110, label: 'AI Service', color: '#C76D4A' }, { x: 60, y: 190, label: 'Database', color: '#5F6B6D' }, { x: 300, y: 190, label: 'Cache', color: '#5F6B6D' }, ]; const edges = [[0,1],[0,2],[0,3],[1,4],[2,4],[3,5]]; return ( ); } function WaveStreamDiagram() { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 40); return () => clearInterval(id); }, []); const W = 480, H = 160; const streams = [ { color: '#D49A2A', amp: 28, freq: 0.022, phase: 0, y: 50 }, { color: '#C46A4D', amp: 20, freq: 0.03, phase: 1.5, y: 85 }, { color: '#2F8F6B', amp: 24, freq: 0.018, phase: 3, y: 120 }, ]; const buildPath = (s) => { const pts = Array.from({ length: 60 }, (_, i) => { const x = (i / 59) * W; const y = s.y + s.amp * Math.sin(x * s.freq + tick * 0.08 + s.phase); return `${i === 0 ? 'M' : 'L'}${x.toFixed(1)},${y.toFixed(1)}`; }); return pts.join(' '); }; return ( ); } function OrbitDiagram() { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 50); return () => clearInterval(id); }, []); const cx = 140, cy = 110; const orbits = [ { r: 40, speed: 0.04, color: '#D49A2A', label: 'داده', dotR: 7 }, { r: 65, speed: -0.025, color: '#C46A4D', label: 'مدل', dotR: 9 }, { r: 90, speed: 0.016, color: '#2F8F6B', label: 'استنتاج', dotR: 8 }, ]; return ( ); } function GeneratedDiagram({ variant = 1, compact = false }) { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick((t) => t + 1), 50); return () => clearInterval(id); }, []); const W = compact ? 320 : 520; const H = compact ? 150 : 210; const seed = Number.isFinite(variant) ? variant : 1; const nodeCount = 6 + (seed % 7); const radius = compact ? 36 + (seed % 5) * 6 : 48 + (seed % 6) * 7; const centerX = W * 0.5; const centerY = H * 0.48; const palette = ['#0F6B73', '#D49A2A', '#C76D4A', '#2F8F6B', '#5F6B6D']; const points = Array.from({ length: nodeCount }, (_, i) => { const angle = ((Math.PI * 2) / nodeCount) * i + (seed % 9) * 0.11; return { x: centerX + Math.cos(angle) * radius, y: centerY + Math.sin(angle) * radius, color: palette[(i + seed) % palette.length] }; }); const pulse = (tick + seed * 3) % 100; return ( ); } function BrainDiagram({ compact = false }) { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 60); return () => clearInterval(id); }, []); const W = compact ? 300 : 400, H = compact ? 180 : 260; const cx = W / 2, cy = H * 0.45; const nodes = [ { x: cx, y: cy - 60 }, { x: cx - 50, y: cy - 30 }, { x: cx + 50, y: cy - 30 }, { x: cx - 70, y: cy + 20 }, { x: cx + 70, y: cy + 20 }, { x: cx, y: cy + 60 }, { x: cx - 30, y: cy + 40 }, { x: cx + 30, y: cy + 40 } ]; return ( ); } function DatabaseDiagram({ compact = false }) { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 50); return () => clearInterval(id); }, []); const W = 320, H = 200; const stacks = [ { x: 60, y: 140, h: 40, color: '#5F6B6D' }, { x: 160, y: 140, h: 60, color: '#D49A2A' }, { x: 260, y: 140, h: 50, color: '#0F6B73' }, ]; return ( ); } function CloudDiagram({ compact = false }) { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 80); return () => clearInterval(id); }, []); return ( ); } function QuantumDiagram({ compact = false }) { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 40); return () => clearInterval(id); }, []); const cx1 = 120, cy = 100, cx2 = 280; const orbit = tick * 0.05; return ( ); } function VlaDiagram({ compact = false }) { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 50); return () => clearInterval(id); }, []); return ( ); } function DnaDiagram({ compact = false }) { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 60); return () => clearInterval(id); }, []); const W = 320, H = 200; const nodes = Array.from({ length: 10 }, (_, i) => i); return ( ); } function FusionDiagram({ compact = false }) { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 40); return () => clearInterval(id); }, []); const cx = 160, cy = 100; return ( ); } function SatelliteDiagram({ compact = false }) { const [tick, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 50); return () => clearInterval(id); }, []); const cx = 160, cy = 100; const satX = cx + Math.cos(tick * 0.03) * 80; const satY = cy + Math.sin(tick * 0.03) * 40; return ( ); } function BlockchainDiagram({ compact = false }) { const blocks = [0, 1, 2, 3]; return ( ); } function TekRagThreeDiagram({ variant = 'corpus', compact = false }) { const hostRef = useRef(null); const [hoverLabel, setHoverLabel] = useState('TekRAG-Persian'); useEffect(() => { const host = hostRef.current; if (!host) return undefined; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100); camera.position.set(0, 3.2, 8.5); const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2)); renderer.outputColorSpace = THREE.SRGBColorSpace; host.appendChild(renderer.domElement); const group = new THREE.Group(); scene.add(group); scene.add(new THREE.AmbientLight(0xffffff, 0.7)); const key = new THREE.DirectionalLight(0xffffff, 1.4); key.position.set(4, 6, 5); scene.add(key); const rim = new THREE.DirectionalLight(0xd49a2a, 0.8); rim.position.set(-5, 3, -4); scene.add(rim); const pickables = []; const palette = { teal: 0x0f6b73, gold: 0xd49a2a, clay: 0xc76d4a, green: 0x2f8f6b, ink: 0x20343a, line: 0xe4ddd2, red: 0xc94c4c, cream: 0xf4efe6, }; const addLabel = (object, label) => { object.userData.label = label; pickables.push(object); return object; }; const box = (label, position, scale, color, opacity = 0.92) => { const mesh = new THREE.Mesh( new THREE.BoxGeometry(scale[0], scale[1], scale[2]), new THREE.MeshStandardMaterial({ color, roughness: 0.48, metalness: 0.12, transparent: opacity < 1, opacity }) ); mesh.position.set(...position); group.add(addLabel(mesh, label)); const edges = new THREE.LineSegments( new THREE.EdgesGeometry(mesh.geometry), new THREE.LineBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0.18 }) ); mesh.add(edges); return mesh; }; const sphere = (label, position, radius, color, opacity = 0.95) => { const mesh = new THREE.Mesh( new THREE.SphereGeometry(radius, 28, 18), new THREE.MeshStandardMaterial({ color, roughness: 0.35, metalness: 0.2, transparent: opacity < 1, opacity }) ); mesh.position.set(...position); group.add(addLabel(mesh, label)); return mesh; }; const line = (from, to, color = palette.line, opacity = 0.45) => { const geometry = new THREE.BufferGeometry().setFromPoints([ new THREE.Vector3(...from), new THREE.Vector3(...to), ]); const mesh = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color, transparent: true, opacity })); group.add(mesh); return mesh; }; if (variant === 'corpus') { const layers = [ ['Raw HTML export', -1.8, palette.ink], ['Persian normalization', -0.6, palette.teal], ['Heading-aware chunks', 0.6, palette.gold], ['Metadata and provenance', 1.8, palette.green], ]; layers.forEach(([label, y, color], idx) => { const slab = box(label, [0, y, 0], [5.8, 0.22, 3.2], color, 0.42); slab.rotation.y = idx % 2 ? 0.08 : -0.08; for (let i = 0; i < 9; i += 1) { const x = -2.2 + (i % 3) * 2.2 + (idx % 2 ? 0.15 : -0.1); const z = -1.05 + Math.floor(i / 3) * 1.05; const doc = sphere(`${label}: document ${i + 1}`, [x, y + 0.28, z], 0.09, idx % 2 ? palette.cream : palette.gold, 0.82); doc.scale.y = 0.55; } }); for (let i = 0; i < 8; i += 1) { const x = -2.3 + (i % 4) * 1.55; const z = -1.35 + (i % 2) * 2.7; line([x, -1.65, z], [x * 0.72, 1.95, z * 0.55], palette.gold, 0.36); } sphere('Benchmark release: QA plus evidence IDs', [0, 2.45, 0], 0.38, palette.clay); camera.position.set(0, 4.1, 8.2); } else if (variant === 'retrieval') { line([-3.3, 0, 0], [3.3, 0, 0], palette.teal, 0.5); line([0, -2.2, 0], [0, 2.2, 0], palette.gold, 0.5); line([0, 0, -2.8], [0, 0, 2.8], palette.green, 0.5); const clusters = [ ['BM25 exact acronym region', [-1.75, 0.45, -0.6], palette.gold], ['Dense semantic Persian region', [1.55, 0.1, 0.75], palette.teal], ['Hybrid fused evidence region', [0.2, 1.2, -0.1], palette.green], ]; clusters.forEach(([label, center, color], ci) => { sphere(label, center, 0.3, color, 0.82); for (let i = 0; i < 18; i += 1) { const a = (i / 18) * Math.PI * 2; const r = 0.35 + (i % 5) * 0.09; const p = [ center[0] + Math.cos(a) * r, center[1] + Math.sin(a * 1.7) * 0.38, center[2] + Math.sin(a) * r, ]; sphere(`${label}: chunk ${i + 1}`, p, 0.055, color, 0.76); } }); const query = sphere('Persian technical user query', [-3.0, -1.45, 1.7], 0.22, palette.red); clusters.forEach(([, center], i) => line(query.position.toArray(), center, i === 1 ? palette.teal : palette.gold, 0.48)); box('Reranker: top-k evidence gate', [0, -1.55, 0], [1.9, 0.16, 1.0], palette.ink, 0.68); camera.position.set(0.2, 2.9, 7.4); } else { const metrics = [ ['Recall@k', -2.4, 1.55, palette.teal], ['Citation precision', -1.2, 2.1, palette.green], ['Atomic support precision', 0, 2.45, palette.gold], ['Abstention F1', 1.2, 1.65, palette.clay], ['Unsupported-claim rate', 2.4, 0.9, palette.red], ]; metrics.forEach(([label, x, h, color]) => { const pillar = box(label, [x, h / 2 - 1.2, 0], [0.52, h, 0.52], color, 0.9); const cap = sphere(`${label}: confidence interval marker`, [x, h - 1.0, 0], 0.18, color, 0.95); line([x, h - 1.0, -0.65], [x, h - 1.0, 0.65], color, 0.48); pillar.rotation.y = 0.2; cap.scale.y = 0.7; }); const ringGeo = new THREE.TorusGeometry(1.55, 0.025, 12, 96); const ring = new THREE.Mesh(ringGeo, new THREE.MeshStandardMaterial({ color: palette.teal, transparent: true, opacity: 0.5 })); ring.rotation.x = Math.PI / 2; ring.position.y = -1.05; group.add(addLabel(ring, 'Paired statistical testing and confidence intervals')); for (let i = 0; i < 14; i += 1) { const a = (i / 14) * Math.PI * 2; sphere('Hallucination error atom', [Math.cos(a) * 1.55, -1.05, Math.sin(a) * 1.55], 0.065, i % 3 === 0 ? palette.red : palette.gold, 0.82); } camera.position.set(0, 3.0, 7.2); } const raycaster = new THREE.Raycaster(); const pointer = new THREE.Vector2(); let raf = 0; let dragging = false; let lastX = 0; let lastY = 0; let targetX = -0.16; let targetY = 0.34; renderer.domElement.style.display = 'block'; const resize = () => { const rect = host.getBoundingClientRect(); const width = Math.max(rect.width || host.offsetWidth || 600, 280); const height = compact ? 240 : 340; renderer.setSize(width, height); camera.aspect = width / height; camera.updateProjectionMatrix(); }; resize(); requestAnimationFrame(resize); const resizeObserver = new ResizeObserver(resize); resizeObserver.observe(host); const updatePointer = (event) => { const rect = renderer.domElement.getBoundingClientRect(); pointer.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; pointer.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; raycaster.setFromCamera(pointer, camera); const hit = raycaster.intersectObjects(pickables, true)[0]; const label = hit?.object?.userData?.label || hit?.object?.parent?.userData?.label; if (label) setHoverLabel(label); if (dragging) { targetY += (event.clientX - lastX) * 0.008; targetX += (event.clientY - lastY) * 0.006; lastX = event.clientX; lastY = event.clientY; } }; const pointerDown = (event) => { dragging = true; lastX = event.clientX; lastY = event.clientY; renderer.domElement.setPointerCapture?.(event.pointerId); }; const pointerUp = (event) => { dragging = false; renderer.domElement.releasePointerCapture?.(event.pointerId); }; renderer.domElement.addEventListener('pointermove', updatePointer); renderer.domElement.addEventListener('pointerdown', pointerDown); renderer.domElement.addEventListener('pointerup', pointerUp); renderer.domElement.addEventListener('pointerleave', pointerUp); const animate = () => { targetY += dragging ? 0 : 0.003; group.rotation.x += (targetX - group.rotation.x) * 0.08; group.rotation.y += (targetY - group.rotation.y) * 0.08; renderer.render(scene, camera); raf = requestAnimationFrame(animate); }; animate(); return () => { cancelAnimationFrame(raf); resizeObserver.disconnect(); renderer.domElement.removeEventListener('pointermove', updatePointer); renderer.domElement.removeEventListener('pointerdown', pointerDown); renderer.domElement.removeEventListener('pointerup', pointerUp); renderer.domElement.removeEventListener('pointerleave', pointerUp); renderer.dispose(); scene.traverse((object) => { object.geometry?.dispose?.(); if (Array.isArray(object.material)) object.material.forEach((m) => m.dispose?.()); else object.material?.dispose?.(); }); host.replaceChildren(); }; }, [variant, compact]); const labels = { corpus: ['Raw', 'Cleaned', 'Metadata', 'Provenance'], retrieval: ['BM25', 'Dense', 'Hybrid', 'Rerank'], evaluation: ['Recall', 'Citation', 'Support', 'Abstention'], }[variant] || ['TekRAG', 'RAG', 'QA']; return (