// Адаптер реальных данных → нейтральная модель движка force-графа. // // Источник — результат buildGraphModel() из network-view.js (он уже нормализует ответ // authService.getUserConnectionsGraph в роли/направления/метки). Здесь только конвертация // в форму, которую понимает движок ({ focusId, nodes[] }). Сервер не трогаем — это чтение. function normLogin(value) { return String(value || '').trim(); } const FAMILY_ROLES = ['parent', 'child', 'spouse', 'sibling']; function relationTypeFromRole(role) { if (FAMILY_ROLES.includes(role)) return 'family'; if (role === 'friend') return 'friend'; return 'contact'; } // Сила связи (0..1) → радиус орбиты в движке. Реальный API пока не отдаёт численную силу, // поэтому выводим её эвристически из роли и направления связи: // - родственники держим ближе всего, контакты — дальше всего; // - взаимные дружеские связи ближе односторонних. function deriveStrength(relation) { if (relation.isRelative) return 0.9; if (relation.role === 'contact') return 0.4; if (relation.forward && relation.backward) return 0.8; return 0.55; } /** * @param {{centerLogin:string, centerMark:object|null, relations:Array}} graphModel * @returns {{focusId:string, nodes:Array}} */ export function engineModelFromGraphModel(graphModel) { const focusLogin = normLogin(graphModel?.centerLogin); const centerMark = graphModel?.centerMark || null; const focusNode = { id: focusLogin, login: focusLogin, name: '', avatar: centerMark?.avatar || null, relationType: 'self', strength: 1, shining: Boolean(centerMark?.shine), tier: 1, }; const relations = Array.isArray(graphModel?.relations) ? graphModel.relations : []; const seen = new Set(); const nodes = relations .map((r) => { const login = normLogin(r?.login); const key = login.toLowerCase(); // исключаем сам фокус (не должно быть линии на собственный ник) и дубли if (!login || key === focusLogin.toLowerCase() || seen.has(key)) return null; seen.add(key); return { id: login, login, name: '', avatar: r?.mark?.avatar || null, relationType: relationTypeFromRole(r?.role), strength: deriveStrength(r || {}), shining: Boolean(r?.mark?.shine), tier: 1, }; }) .filter(Boolean); return { focusId: focusLogin, nodes: [focusNode, ...nodes] }; }