(nodes: Array<{ id: string }>, edges: Array<{ from: string; to: string }>)
| 161 | } |
| 162 | |
| 163 | function calculateLongestChain(nodes: Array<{ id: string }>, edges: Array<{ from: string; to: string }>): number { |
| 164 | if (nodes.length === 0) return 0 |
| 165 | |
| 166 | // Build adjacency list for forward traversal |
| 167 | const graph = new Map<string, string[]>() |
| 168 | for (const node of nodes) { |
| 169 | graph.set(node.id, []) |
| 170 | } |
| 171 | for (const edge of edges) { |
| 172 | const neighbors = graph.get(edge.from) |
| 173 | if (neighbors) { |
| 174 | neighbors.push(edge.to) |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | // Find blocks with no incoming edges (entry points) |
| 179 | const incomingCount = new Map<string, number>() |
| 180 | for (const node of nodes) { |
| 181 | incomingCount.set(node.id, 0) |
| 182 | } |
| 183 | for (const edge of edges) { |
| 184 | const count = incomingCount.get(edge.to) ?? 0 |
| 185 | incomingCount.set(edge.to, count + 1) |
| 186 | } |
| 187 | |
| 188 | // Topological sort with BFS to find longest path |
| 189 | const maxDepth = new Map<string, number>() |
| 190 | const queue: string[] = [] |
| 191 | |
| 192 | for (const node of nodes) { |
| 193 | if (incomingCount.get(node.id) === 0) { |
| 194 | queue.push(node.id) |
| 195 | maxDepth.set(node.id, 1) |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | while (queue.length > 0) { |
| 200 | const nodeId = queue.shift() |
| 201 | if (!nodeId) break |
| 202 | const currentDepth = maxDepth.get(nodeId) ?? 1 |
| 203 | const neighbors = graph.get(nodeId) ?? [] |
| 204 | |
| 205 | for (const neighbor of neighbors) { |
| 206 | const newDepth = currentDepth + 1 |
| 207 | const existingDepth = maxDepth.get(neighbor) ?? 0 |
| 208 | if (newDepth > existingDepth) { |
| 209 | maxDepth.set(neighbor, newDepth) |
| 210 | } |
| 211 | |
| 212 | const count = incomingCount.get(neighbor) ?? 0 |
| 213 | incomingCount.set(neighbor, count - 1) |
| 214 | if (count - 1 === 0) { |
| 215 | queue.push(neighbor) |
| 216 | } |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | return Math.max(0, ...maxDepth.values()) |
no outgoing calls
no test coverage detected