// ════════════════════════════════════════════════════════════════ // StartupCard — детальная карточка компании из реестра // Открывается при клике на строку CorpusPage // ════════════════════════════════════════════════════════════════ const { useMemo: useMemoStartup } = React; function StartupCard({ startup, onClose }) { const D = window.SDH_DATA; const s = startup; // generate deterministic mock detail data from id const seed = s.id; function pr(n) { return ((seed * 9301 + n * 49297) % 233280) / 233280; } const fundingRound = s.funding_usd ? (pr(1) < 0.4 ? 'Seed' : pr(1) < 0.7 ? 'Series A' : 'Series B') : 'pre-seed'; const teamSize = 3 + Math.floor(pr(2) * 28); const founded = 2018 + Math.floor(pr(3) * 7); const website = `${s.name.toLowerCase().replace(/\s+/g, '')}.com`; // related ideas (5 from corpus seed) const relatedIdeas = useMemoStartup(() => { return Array.from({ length: 3 }).map((_, k) => { const idx = Math.floor(pr(10 + k) * D.ideas.length); return D.ideas[idx]; }); }, [seed]); // mention timeseries (28 days) const timeseries = useMemoStartup(() => { return Array.from({ length: 28 }).map((_, t) => ({ value: Math.max(0, Math.round((pr(t + 50) * 8) + (t === 27 ? 6 : 0))), })); }, [seed]); const totalMentions = timeseries.reduce((sum, p) => sum + p.value, 0); // signal tags const tags = useMemoStartup(() => { const all = ['B2B', 'B2C', 'enterprise', 'SaaS', 'open-source', 'API-first', 'on-prem', 'compliance', 'мобильное', 'edge']; return all.filter((_, i) => pr(100 + i) > 0.65).slice(0, 4); }, [seed]); const similarityZone = s.similarity < 0.5 ? { hue: 'rose', label: 'низкая' } : s.similarity < 0.75 ? { hue: 'amber', label: 'средняя' } : { hue: 'emerald', label: 'высокая' }; return (
{s.desc}
{s.similarity >= 0.75 ? 'Высокая близость к фокусу исследования. Рекомендуем поставить на еженедельный мониторинг.' : s.similarity >= 0.5 ? 'Средняя релевантность. Дополнительный сигнал нужен для принятия решения.' : 'Низкая близость. Включён в корпус как контекстная единица.'}