(sourceNodes, sourceEdges)
| 3364 | } |
| 3365 | |
| 3366 | function conceptEntriesFromGraph(sourceNodes, sourceEdges) { |
| 3367 | const degree = graphDegreeMap(sourceNodes, sourceEdges); |
| 3368 | const entries = new Map(); |
| 3369 | sourceNodes.forEach((node) => { |
| 3370 | const nodeId = graphId(node); |
| 3371 | const type = graphType(node); |
| 3372 | const base = type === "paper" ? 2 : type === "frontier" ? 1.3 : type === "method" ? 0.9 : 1; |
| 3373 | candidateLabelsForNode(node).forEach((label, index) => { |
| 3374 | if (!entries.has(label)) { |
| 3375 | entries.set(label, { label, score: 0, nodeIds: new Set(), nodes: [] }); |
| 3376 | } |
| 3377 | const entry = entries.get(label); |
| 3378 | entry.score += base + Math.min(2.5, degree[nodeId] || 0) * 0.18 + (8 - index) * 0.04; |
| 3379 | entry.nodeIds.add(nodeId); |
| 3380 | entry.nodes.push(node); |
| 3381 | }); |
| 3382 | }); |
| 3383 | return dedupeConceptEntries(Array.from(entries.values()).sort((a, b) => b.score - a.score)); |
| 3384 | } |
| 3385 | |
| 3386 | function dedupeConceptEntries(entries) { |
| 3387 | const selected = []; |
no test coverage detected