• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

graphty-org / graphty-monorepo / 20661584252

02 Jan 2026 03:50PM UTC coverage: 77.924% (+7.3%) from 70.62%
20661584252

push

github

apowers313
ci: fix flakey performance test

13438 of 17822 branches covered (75.4%)

Branch coverage included in aggregate %.

41247 of 52355 relevant lines covered (78.78%)

145534.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.77
/graphty-element/src/algorithms/utils/communityUtils.ts
1
/**
2
 * @file Shared utilities for community detection algorithms
3
 */
4

5
import type { GraphLike } from "./graphUtils";
6

7
/**
8
 * Options for community utilities
9
 */
10
export interface CommunityOptions {
11
    /** Weight attribute name on edges (default: "value") */
12
    weightAttribute?: string;
13
}
14

15
/**
16
 * Options for degree calculation
17
 */
18
export interface DegreeOptions {
19
    /** Whether to treat the graph as directed (default: false for undirected) */
20
    directed?: boolean;
21
    /** For directed graphs, count "in", "out", or "both" edges (default: "both") */
22
    countType?: "in" | "out" | "both";
23
}
24

25
/**
26
 * Convert a community assignment map to an array of arrays.
27
 *
28
 * Takes a Map where keys are node IDs and values are community IDs,
29
 * and returns an array where each element is an array of node IDs in that community.
30
 * @param communities - Map of node ID to community ID
31
 * @returns Array of arrays, where each inner array contains node IDs in the same community
32
 * @example
33
 * ```typescript
34
 * const communities = new Map([["A", 0], ["B", 0], ["C", 1]]);
35
 * const result = extractCommunities(communities);
36
 * // result: [["A", "B"], ["C"]]
37
 * ```
38
 */
39
export function extractCommunities(communities: Map<number | string, number>): (number | string)[][] {
15✔
40
    const communityArrays = new Map<number, (number | string)[]>();
5✔
41

42
    for (const [nodeId, communityId] of communities) {
5✔
43
        let communityArray = communityArrays.get(communityId);
12✔
44

45
        if (communityArray === undefined) {
12✔
46
            communityArray = [];
9✔
47
            communityArrays.set(communityId, communityArray);
9✔
48
        }
9✔
49

50
        communityArray.push(nodeId);
12✔
51
    }
12✔
52

53
    return Array.from(communityArrays.values());
5✔
54
}
5✔
55

56
/**
57
 * Get the total weight of all edges in the graph.
58
 * @param graph - The graphty-element Graph instance
59
 * @param options - Configuration options
60
 * @returns Total edge weight
61
 * @example
62
 * ```typescript
63
 * const totalWeight = getTotalEdgeWeight(graph);
64
 * ```
65
 */
66
export function getTotalEdgeWeight(graph: GraphLike, options: CommunityOptions = {}): number {
15✔
67
    const { weightAttribute = "value" } = options;
4✔
68
    const { edges } = graph.getDataManager();
4✔
69

70
    let totalWeight = 0;
4✔
71

72
    for (const edge of edges.values()) {
4✔
73
        const edgeData = edge.data;
5✔
74
        let rawWeight = edgeData?.[weightAttribute];
5!
75

76
        if (rawWeight === undefined) {
5✔
77
            rawWeight = edge[weightAttribute];
5✔
78
        }
5✔
79

80
        const weight: number = typeof rawWeight === "number" ? rawWeight : 1;
5✔
81
        totalWeight += weight;
5✔
82
    }
5✔
83

84
    return totalWeight;
4✔
85
}
4✔
86

87
/**
88
 * Get the degree of a specific node.
89
 *
90
 * In undirected mode (default), counts all edges incident to the node.
91
 * In directed mode, can count incoming, outgoing, or both edges.
92
 * @param graph - The graphty-element Graph instance
93
 * @param nodeId - The ID of the node
94
 * @param options - Configuration options
95
 * @returns The degree of the node
96
 * @example
97
 * ```typescript
98
 * // Undirected degree
99
 * const degree = getNodeDegree(graph, "A");
100
 *
101
 * // Directed out-degree
102
 * const outDegree = getNodeDegree(graph, "A", { directed: true, countType: "out" });
103
 * ```
104
 */
105
export function getNodeDegree(graph: GraphLike, nodeId: number | string, options: DegreeOptions = {}): number {
15✔
106
    const { directed = false, countType = "both" } = options;
6✔
107
    const { edges } = graph.getDataManager();
6✔
108

109
    let degree = 0;
6✔
110
    const nodeIdStr = String(nodeId);
6✔
111

112
    for (const edge of edges.values()) {
6✔
113
        const srcIdStr = String(edge.srcId);
8✔
114
        const dstIdStr = String(edge.dstId);
8✔
115

116
        if (directed) {
8✔
117
            if (countType === "out" && srcIdStr === nodeIdStr) {
4✔
118
                degree++;
1✔
119
            } else if (countType === "in" && dstIdStr === nodeIdStr) {
4✔
120
                degree++;
2✔
121
            } else if (countType === "both") {
3!
122
                if (srcIdStr === nodeIdStr || dstIdStr === nodeIdStr) {
×
123
                    degree++;
×
124
                }
×
125
            }
×
126
        } else {
4✔
127
            // Undirected: count if node is either source or destination
128
            if (srcIdStr === nodeIdStr || dstIdStr === nodeIdStr) {
4✔
129
                degree++;
4✔
130
            }
4✔
131
        }
4✔
132
    }
8✔
133

134
    return degree;
6✔
135
}
6✔
136

137
/**
138
 * Count the number of unique communities in a community assignment map.
139
 * @param communities - Map of node ID to community ID
140
 * @returns Number of unique communities
141
 * @example
142
 * ```typescript
143
 * const communities = new Map([["A", 0], ["B", 0], ["C", 1]]);
144
 * const count = countUniqueCommunities(communities);
145
 * // count: 2
146
 * ```
147
 */
148
export function countUniqueCommunities(communities: Map<number | string, number>): number {
15✔
149
    const uniqueCommunities = new Set<number>();
9✔
150

151
    for (const communityId of communities.values()) {
9✔
152
        uniqueCommunities.add(communityId);
91✔
153
    }
91✔
154

155
    return uniqueCommunities.size;
9✔
156
}
9✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc