Files

79 lines
3.2 KiB
JavaScript

// Адаптер реальных данных → нейтральная модель движка force-графа.
//
// Источник — результат buildGraphModel() из network-view.js (он уже нормализует ответ
// authService.getUserConnectionsGraph в роли/направления/метки). Здесь только конвертация
// в форму, которую понимает движок ({ focusId, nodes[] }). Сервер не трогаем — это чтение.
function normLogin(value) {
return String(value || '').trim();
}
const FAMILY_ROLES = ['parent', 'child', 'spouse', 'sibling'];
function relationTypeFromRelation(relation) {
const explicit = String(relation?.mark?.relationType || '').trim().toLowerCase();
if (explicit === 'close_friend' || explicit === 'friend' || explicit === 'contact') return explicit;
const role = relation?.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?.mark?.relationType === 'close_friend') 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: centerMark?.displayName || centerMark?.login || focusLogin,
avatar: centerMark?.avatar || null,
relationType: 'self',
strength: 1,
shining: Boolean(centerMark?.shine),
official: Boolean(centerMark?.official),
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: r?.mark?.displayName || login,
avatar: r?.mark?.avatar || null,
relationType: relationTypeFromRelation(r),
strength: deriveStrength(r || {}),
shining: Boolean(r?.mark?.shine),
official: Boolean(r?.mark?.official),
tier: 1,
};
})
.filter(Boolean);
return { focusId: focusLogin, nodes: [focusNode, ...nodes] };
}