lint: change folder names
This commit is contained in:
123
frontend/src/lib/graph/graphPath.ts
Normal file
123
frontend/src/lib/graph/graphPath.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Graph path utilities: compute which nodes/edges are "on the path" of an update.
|
||||
* Used to show connection ant trail only along the full chain (upstream → updating → downstream).
|
||||
* Works with any node types; any node can signal it is updating via startConnectionPathUpdate(id).
|
||||
*/
|
||||
|
||||
export type GraphEdge = { source: string; target: string }
|
||||
|
||||
/** Nodes reachable from seedIds by following edges forward (source → target). */
|
||||
export function getDownstreamNodeIds(edges: GraphEdge[], seedIds: string[]): Set<string> {
|
||||
const out = new Set<string>(seedIds)
|
||||
let added = true
|
||||
while (added) {
|
||||
added = false
|
||||
for (const e of edges) {
|
||||
if (out.has(e.source) && !out.has(e.target)) {
|
||||
out.add(e.target)
|
||||
added = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
/** Nodes that can reach any seed by following edges backward (target → source). */
|
||||
export function getUpstreamNodeIds(edges: GraphEdge[], seedIds: string[]): Set<string> {
|
||||
const out = new Set<string>(seedIds)
|
||||
let added = true
|
||||
while (added) {
|
||||
added = false
|
||||
for (const e of edges) {
|
||||
if (out.has(e.target) && !out.has(e.source)) {
|
||||
out.add(e.source)
|
||||
added = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
/**
|
||||
* All node ids that lie on the path of an update.
|
||||
* - If updatingNodeIds non-empty: path = downstream(trigger) ∩ (upstream(updating) ∪ downstream(updating))
|
||||
* so we include config→agent→rendering when agent is running.
|
||||
* - Else if triggerNodeIds and pausedNodeIds non-empty: path = downstream(trigger) ∩ upstream(paused)
|
||||
* so we show yellow (config→agent) when config changed and agent is on hold.
|
||||
* An edge should show color iff both its source and target are in this set.
|
||||
*/
|
||||
export function getPathNodeIds(
|
||||
edges: GraphEdge[],
|
||||
updatingNodeIds: string[],
|
||||
triggerNodeIds?: string[],
|
||||
pausedNodeIds?: string[]
|
||||
): Set<string> {
|
||||
const hasUpdating = updatingNodeIds.length > 0
|
||||
const hasPausedPath =
|
||||
pausedNodeIds != null &&
|
||||
pausedNodeIds.length > 0 &&
|
||||
triggerNodeIds != null &&
|
||||
triggerNodeIds.length > 0
|
||||
|
||||
if (hasUpdating && triggerNodeIds != null && triggerNodeIds.length > 0) {
|
||||
const downstreamOfTrigger = getDownstreamNodeIds(edges, triggerNodeIds)
|
||||
const upstreamOfUpdating = getUpstreamNodeIds(edges, updatingNodeIds)
|
||||
const downstreamOfUpdating = getDownstreamNodeIds(edges, updatingNodeIds)
|
||||
const path = new Set<string>()
|
||||
downstreamOfTrigger.forEach((id) => {
|
||||
if (upstreamOfUpdating.has(id) || downstreamOfUpdating.has(id)) path.add(id)
|
||||
})
|
||||
return path
|
||||
}
|
||||
|
||||
if (hasPausedPath && !hasUpdating) {
|
||||
const upstream = getUpstreamNodeIds(edges, pausedNodeIds!)
|
||||
const downstreamOfTrigger = getDownstreamNodeIds(edges, triggerNodeIds!)
|
||||
const path = new Set<string>()
|
||||
upstream.forEach((id) => {
|
||||
if (downstreamOfTrigger.has(id)) path.add(id)
|
||||
})
|
||||
return path
|
||||
}
|
||||
|
||||
if (hasUpdating) {
|
||||
const upstream = getUpstreamNodeIds(edges, updatingNodeIds)
|
||||
const downstream = getDownstreamNodeIds(edges, updatingNodeIds)
|
||||
const path = new Set<string>(upstream)
|
||||
downstream.forEach((id) => path.add(id))
|
||||
return path
|
||||
}
|
||||
|
||||
return new Set()
|
||||
}
|
||||
|
||||
/**
|
||||
* Path nodes from triggers up to and including the first paused node (Archon on hold).
|
||||
* Used to color those edges yellow; rest of path stays blue.
|
||||
*/
|
||||
export function getPausedSegmentNodeIds(
|
||||
edges: GraphEdge[],
|
||||
pathNodeIds: Set<string>,
|
||||
triggerNodeIds: string[],
|
||||
pausedNodeIds: string[]
|
||||
): Set<string> {
|
||||
if (pausedNodeIds.length === 0 || triggerNodeIds.length === 0) return new Set()
|
||||
const pausedSet = new Set(pausedNodeIds)
|
||||
const seeds = triggerNodeIds.filter((id) => pathNodeIds.has(id))
|
||||
if (seeds.length === 0) return new Set()
|
||||
const out = new Set<string>(seeds)
|
||||
const frontier: string[] = [...seeds]
|
||||
const visited = new Set<string>(seeds)
|
||||
while (frontier.length > 0) {
|
||||
const n = frontier.shift()!
|
||||
if (pausedSet.has(n)) continue
|
||||
for (const e of edges) {
|
||||
if (e.source !== n || !pathNodeIds.has(e.target) || visited.has(e.target)) continue
|
||||
visited.add(e.target)
|
||||
out.add(e.target)
|
||||
if (pausedSet.has(e.target)) continue
|
||||
frontier.push(e.target)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user