diff --git a/app/teknav-diagrams.jsx b/app/teknav-diagrams.jsx new file mode 100644 index 0000000..9d149d6 --- /dev/null +++ b/app/teknav-diagrams.jsx @@ -0,0 +1,1181 @@ +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 ( + + {layers.map((layer, li) => + layers[li + 1] && layer.nodes.map((fy, fi) => + layers[li + 1].nodes.map((ty, ti) => ( + + )) + ) + )} + {pulses.map((p, i) => ( + + ))} + {layers.map((layer, li) => + layer.nodes.map((y, ni) => ( + setHovered(`${li}-${ni}`)} onMouseLeave={() => setHovered(null)} style={{ cursor: 'pointer' }}> + + {hovered === `${li}-${ni}` && ( + + + {layer.label} + + )} + + )) + )} + {layers.map((layer, li) => ( + {layer.label} + ))} + + ); +} +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 ( + + + {[0, 25, 50, 75].map(offset => { + const pos = ((tick + offset) % 100) / 100; + const x = stepW * 0.5 + pos * (W - stepW); + return ; + })} + {steps.map((step, i) => { + const cx = stepW * (i + 0.5); + const isHov = hovered === step.id; + return ( + setHovered(step.id)} onMouseLeave={() => setHovered(null)} style={{ cursor: 'pointer' }}> + + {i + 1} + {step.label} + {isHov && ( + + + {step.desc} + + )} + + ); + })} + + ); +} +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 ( + + + + + + + + سرور مرکزی + + {threats.map((t, i) => { + const rad = (t.angle * Math.PI) / 180; + const tx = cx + Math.cos(rad) * r; + const ty = cy + Math.sin(rad) * r; + const lx = cx + Math.cos(rad) * (r + 38); + const ly = cy + Math.sin(rad) * (r + 38); + const isH = hovered === i; + const pulse = (tick + i * 6) % 30 < 15; + return ( + setHovered(i)} onMouseLeave={() => setHovered(null)} style={{ cursor: 'pointer' }}> + + + {isH && ( + + + {t.label} + + )} + + ); + })} + + + ); +} +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 ( + + + + {pathD && } + {pathPoints.length > 1 && ( + + )} + {points.map((p, i) => { + const t = i / (milestones.length - 1); + const visible = t <= drawProgress + 0.01; + return visible ? ( + + + {milestones[i]} + + ) : null; + })} + منحنی رشد استارتاپ + + ); +} +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 ( + + + {routes.map((r, i) => { + const len = Math.hypot(r.x2 - r.x1, r.y2 - r.y1); + const phase = ((tick + i * 12) % 40) / 40; + const px = r.x1 + (r.x2 - r.x1) * phase; + const py = r.y1 + (r.y2 - r.y1) * phase; + return ( + + + + + ); + })} + {blocks.map((b, i) => ( + + + {b.label} + + ))} + + ); +} +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 ( + + + {milestones.map((m, i) => { + const x = 40 + (i / (milestones.length - 1)) * (W - 80); + const isH = activeIdx === i; + return ( + setActiveIdx(i)} onMouseLeave={() => setActiveIdx(null)} style={{ cursor: 'pointer' }}> + + {m.year} + {isH && ( + + + {m.label} + + )} + {!isH && {m.label}} + + ); + })} + + ); +} +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 ( + + {edges.map(([a, b], i) => ( + + ))} + + + + + + {modules.map((m, i) => ( + + + {m.label} + + ))} + + ); +} +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 ( + + + {streams.map((s, i) => ( + + + + + + + ))} + + {streams.map((s, i) => ( + + + {(() => { + const pct = ((tick * 1.8 + i * 80) % 480) / 480; + const x = pct * W; + const y = s.y + s.amp * Math.sin(x * s.freq + tick * 0.08 + s.phase); + 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 ( + + + + AI + {orbits.map((o, i) => ( + + + {(() => { + const angle = tick * o.speed; + const x = cx + o.r * Math.cos(angle); + const y = cy + o.r * Math.sin(angle); + return ( + + + {o.label} + + ); + })()} + + ))} + + ); +} +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 ( + + + {points.map((a, i) => points.slice(i + 1).map((b, j) => ( + + )))} + {points.map((p, i) => ( + + + + + ))} + Generated Diagram {String(seed).padStart(2, '0')} + + ); +} +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 ( + + + + + + + + + {nodes.map((n1, i) => nodes.slice(i + 1).map((n2, j) => { + const dist = Math.hypot(n1.x - n2.x, n1.y - n2.y); + if (dist > 100) return null; + return ; + }))} + {nodes.map((n, i) => { + const pulse = Math.sin(tick * 0.1 + i) * 3 + 6; + 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 ( + + {stacks.map((s, i) => ( + + + + + + ))} + + + + ساختار داده‌های برداری + + ); +} +function CloudDiagram({ compact = false }) { + const [tick, setTick] = useState(0); + useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 80); return () => clearInterval(id); }, []); + return ( + + + {[0, 1, 2].map(i => { + const x = 150 + i * 50, y = 110; + const pulse = (tick + i * 10) % 20 < 10; + 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 ( + + + + VLA MODEL + + + + Vision + + Language + + ACTION + + + ); +} +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 ( + + {nodes.map(i => { + const y = 30 + i * 15; + const x1 = 160 + Math.sin(tick * 0.1 + i * 0.8) * 40; + const x2 = 160 - Math.sin(tick * 0.1 + i * 0.8) * 40; + 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 ( + + {blocks.map(i => ( + + + BLOCK {i} + {i < 3 && } + + ))} + فناوری زنجیره بلوکی و فین‌تک + + ); +} +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 ( +
+
+
+
{hoverLabel}
+
+ {labels.map((label) => {label})} +
+
+
+ ); +} + +function BillingDiagram({ compact = false }) { + const [tick, setTick] = useState(0); + useEffect(() => { const id = setInterval(() => setTick(t => (t + 1) % 120), 80); return () => clearInterval(id); }, []); + const h = compact ? 200 : 280; + const bars = [ + { label: 'Input', base: 40, peak: 110, color: '#0F6B73' }, + { label: 'Output', base: 55, peak: 140, color: '#D49A2A' }, + { label: 'Cache', base: 20, peak: 70, color: '#2F8F6B' }, + { label: 'Image', base: 65, peak: 160, color: '#C76D4A' }, + { label: 'Audio', base: 30, peak: 90, color: '#5F6B6D' }, + ]; + const progress = (Math.sin(tick * 0.08) + 1) / 2; + return ( + + + {bars.map((b, i) => { + const bh = b.base + (b.peak - b.base) * progress; + const x = 40 + i * 72; + return ( + + + + {b.label} + {Math.round(b.base + (b.peak - b.base) * progress)}k + + ); + })} + Token Usage + + {[0, 40, 80, 120, 160].map((v, i) => ( + {v}k + ))} + + ); +} + +function LegalDiagram({ compact = false }) { + const [tick, setTick] = useState(0); + useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 100); return () => clearInterval(id); }, []); + const h = compact ? 200 : 280; + const tilt = Math.sin(tick * 0.05) * 12; + return ( + + + + + + + AI Product + + Liability + + AI Legal Scales + {['CEO', 'Product', 'Corp'].map((t, i) => ( + + + {t} + + ))} + + ); +} + +function MathDiagram({ compact = false }) { + const [tick, setTick] = useState(0); + useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 60); return () => clearInterval(id); }, []); + const h = compact ? 200 : 280; + const nodes = [ + { x: 210, y: 60, label: 'v₁', color: '#D49A2A' }, + { x: 120, y: 120, label: 'v₂', color: '#0F6B73' }, + { x: 300, y: 120, label: 'v₃', color: '#0F6B73' }, + { x: 80, y: 200, label: 'v₄', color: '#2F8F6B' }, + { x: 170, y: 200, label: 'v₅', color: '#2F8F6B' }, + { x: 250, y: 200, label: 'v₆', color: '#2F8F6B' }, + { x: 340, y: 200, label: 'v₇', color: '#C76D4A' }, + ]; + const edges = [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6],[3,4],[4,5],[5,6]]; + const pulse = (tick % 60) / 60; + return ( + + + {edges.map(([a,b], i) => { + const p = (tick * 0.02 + i * 0.3) % 1; + const mx = nodes[a].x + (nodes[b].x - nodes[a].x) * p; + const my = nodes[a].y + (nodes[b].y - nodes[a].y) * p; + return ( + + + + + ); + })} + {nodes.map((n, i) => ( + + + {n.label} + + ))} + Unit Distance Graph — Erdős Conjecture + + ); +} + +function AgentLoopDiagram({ compact = false }) { + const [tick, setTick] = useState(0); + useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 50); return () => clearInterval(id); }, []); + const h = compact ? 200 : 280; + const cx = 210, cy = h / 2, r = compact ? 70 : 90; + const steps = ['Plan', 'Act', 'Observe', 'Reflect']; + const colors = ['#0F6B73', '#D49A2A', '#2F8F6B', '#C76D4A']; + const active = Math.floor(tick / 30) % 4; + return ( + + + {steps.map((s, i) => { + const angle = (i / 4) * Math.PI * 2 - Math.PI / 2; + const nx = cx + Math.cos(angle) * r, ny = cy + Math.sin(angle) * r; + const next = (i + 1) % 4; + const na = (next / 4) * Math.PI * 2 - Math.PI / 2; + const nx2 = cx + Math.cos(na) * r, ny2 = cy + Math.sin(na) * r; + const p = (tick % 30) / 30; + const px = nx + (nx2 - nx) * p, py = ny + (ny2 - ny) * p; + return ( + + + {active === i && } + + {s} + + ); + })} + + Agent + + ); +} + +function GeopoliticsDiagram({ compact = false }) { + const [tick, setTick] = useState(0); + useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 70); return () => clearInterval(id); }, []); + const h = compact ? 200 : 280; + const regions = [ + { x: 100, y: 80, label: 'US', color: '#0F6B73' }, + { x: 200, y: 60, label: 'EU', color: '#D49A2A' }, + { x: 310, y: 80, label: 'China', color: '#C76D4A' }, + { x: 80, y: 180, label: 'India', color: '#2F8F6B' }, + { x: 200, y: 190, label: 'MENA', color: '#5F6B6D' }, + { x: 330, y: 180, label: 'APAC', color: '#0F6B73' }, + ]; + const links = [[0,1],[0,3],[1,2],[1,4],[2,5],[3,4],[4,5]]; + return ( + + + + {links.map(([a, b], i) => { + const p = (tick * 0.015 + i * 0.2) % 1; + const mx = regions[a].x + (regions[b].x - regions[a].x) * p; + const my = regions[a].y + (regions[b].y - regions[a].y) * p; + return ( + + + + + ); + })} + {regions.map((n, i) => ( + + + {n.label} + + ))} + Geopolitical AI Ecosystem + + ); +} + +function BrowserDiagram({ compact = false }) { + const [tick, setTick] = useState(0); + useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 90); return () => clearInterval(id); }, []); + const h = compact ? 200 : 280; + const reqs = [0, 1, 2, 3, 4].map(i => ({ label: ['HTML','CSS','JS','API','WS'][i], color: ['#0F6B73','#D49A2A','#C76D4A','#2F8F6B','#5F6B6D'][i], w: [160,80,120,100,60][i] })); + const progress = (tick % 60) / 60; + return ( + + + + + + + + teknav.ir/article/... + {reqs.map((r, i) => { + const y = 58 + i * 34; + const filled = Math.min(r.w, r.w * (((tick + i * 12) % 60) / 60) * 1.8); + return ( + + {r.label} + + + {Math.round(Math.min(filled, r.w) / r.w * 100)}% + + ); + })} + Browser DevTools — Network + + ); +} + +function MemorySafetyDiagram({ compact = false }) { + const [tick, setTick] = useState(0); + useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 80); return () => clearInterval(id); }, []); + const h = compact ? 200 : 280; + const blocks = [ + { x: 30, label: 'Stack', owned: true }, + { x: 110, label: 'Heap A', owned: true }, + { x: 190, label: 'Heap B', owned: false }, + { x: 270, label: 'Heap C', owned: true }, + { x: 350, label: 'Static', owned: true }, + ]; + const flash = Math.sin(tick * 0.15) > 0.7; + return ( + + + Memory Safety — Rust Ownership + {blocks.map((b, i) => { + const isUnsafe = !b.owned; + const color = isUnsafe ? '#C76D4A' : '#2F8F6B'; + const bh = 60 + Math.sin(tick * 0.05 + i) * 10; + return ( + + + {b.owned ? '✓' : '✗'} + {b.label} + + ); + })} + + use-after-free + + + ); +} + +function MediaDiagram({ compact = false }) { + const [tick, setTick] = useState(0); + useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 60); return () => clearInterval(id); }, []); + const h = compact ? 200 : 280; + const nodes = [ + { x: 60, y: h / 2, label: 'نویسنده', color: '#D49A2A', r: 22 }, + { x: 210, y: h / 2 - 30, label: 'پلتفرم', color: '#0F6B73', r: 28 }, + { x: 210, y: h / 2 + 30, label: 'RSS/Feed', color: '#2F8F6B', r: 20 }, + { x: 360, y: h / 2 - 60, label: 'خواننده ۱', color: '#5F6B6D', r: 16 }, + { x: 360, y: h / 2, label: 'خواننده ۲', color: '#5F6B6D', r: 16 }, + { x: 360, y: h / 2 + 60, label: 'خواننده ۳', color: '#5F6B6D', r: 16 }, + ]; + const edges = [[0,1],[0,2],[1,3],[1,4],[1,5],[2,3],[2,4],[2,5]]; + return ( + + + {edges.map(([a, b], i) => { + const p = (tick * 0.02 + i * 0.15) % 1; + const mx = nodes[a].x + (nodes[b].x - nodes[a].x) * p; + const my = nodes[a].y + (nodes[b].y - nodes[a].y) * p; + return ( + + + + + ); + })} + {nodes.map((n, i) => ( + + + {n.label} + + ))} + Content Distribution Network + + ); +} + +function DiagramRenderer({ type, compact = false }) { + const map = { + neural: NeuralNetworkDiagram, + pipeline: DataPipelineDiagram, + cyber: CyberSecurityDiagram, + growth: StartupGrowthDiagram, + chip: HardwareChipDiagram, + timeline: FutureTimelineDiagram, + arch: SoftwareArchDiagram, + wave: WaveStreamDiagram, + orbit: OrbitDiagram, + brain: BrainDiagram, + database: DatabaseDiagram, + cloud: CloudDiagram, + quantum: QuantumDiagram, + vla: VlaDiagram, + dna: DnaDiagram, + fusion: FusionDiagram, + satellite: SatelliteDiagram, + blockchain: BlockchainDiagram, + billing: BillingDiagram, + legal: LegalDiagram, + math: MathDiagram, + 'agent-loop': AgentLoopDiagram, + geopolitics: GeopoliticsDiagram, + browser: BrowserDiagram, + 'memory-safety': MemorySafetyDiagram, + media: MediaDiagram, + 'tekrag-corpus-3d': (props) => , + 'tekrag-retrieval-3d': (props) => , + 'tekrag-evaluation-3d': (props) => + }; + if (typeof type === 'string' && /^diagram-\d{3}$/.test(type)) { + const variant = Number(type.split('-')[1]); + return ; + } + const Comp = map[type] || NeuralNetworkDiagram; + return ; +} + +export { NeuralNetworkDiagram, DataPipelineDiagram, CyberSecurityDiagram, StartupGrowthDiagram, HardwareChipDiagram, FutureTimelineDiagram, SoftwareArchDiagram, WaveStreamDiagram, OrbitDiagram, GeneratedDiagram, TekRagThreeDiagram, BillingDiagram, LegalDiagram, MathDiagram, AgentLoopDiagram, GeopoliticsDiagram, BrowserDiagram, MemorySafetyDiagram, MediaDiagram, DiagramRenderer };