mirror of
https://github.com/YuzuZensai/Minikura.git
synced 2026-03-30 22:28:37 +00:00
84 lines
2.3 KiB
TypeScript
84 lines
2.3 KiB
TypeScript
|
|
import type { TopologyEdge, TopologyNode } from "@/lib/topology-types";
|
||
|
|
|
||
|
|
const LAYOUT_CONFIG = {
|
||
|
|
TIER_SPACING: 300, // Vertical spacing between proxy and server tiers
|
||
|
|
NODE_SPACING: 250, // Horizontal spacing between nodes
|
||
|
|
START_X: 150, // Left padding
|
||
|
|
START_Y: 100, // Top padding
|
||
|
|
} as const;
|
||
|
|
|
||
|
|
export function applyHierarchicalLayout(
|
||
|
|
nodes: TopologyNode[],
|
||
|
|
edges: TopologyEdge[]
|
||
|
|
): { nodes: TopologyNode[]; edges: TopologyEdge[] } {
|
||
|
|
const proxyNodes = nodes.filter((n) => n.data.type === "proxy");
|
||
|
|
const serverNodes = nodes.filter((n) => n.data.type === "server");
|
||
|
|
|
||
|
|
const layoutedNodes: TopologyNode[] = [];
|
||
|
|
|
||
|
|
const maxNodesInTier = Math.max(proxyNodes.length, serverNodes.length);
|
||
|
|
const tierWidth = maxNodesInTier * LAYOUT_CONFIG.NODE_SPACING;
|
||
|
|
|
||
|
|
const proxyOffsetX = (tierWidth - proxyNodes.length * LAYOUT_CONFIG.NODE_SPACING) / 2;
|
||
|
|
proxyNodes.forEach((node, index) => {
|
||
|
|
const x = LAYOUT_CONFIG.START_X + proxyOffsetX + index * LAYOUT_CONFIG.NODE_SPACING;
|
||
|
|
const y = LAYOUT_CONFIG.START_Y;
|
||
|
|
|
||
|
|
layoutedNodes.push({
|
||
|
|
...node,
|
||
|
|
position: { x, y },
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
const serverOffsetX = (tierWidth - serverNodes.length * LAYOUT_CONFIG.NODE_SPACING) / 2;
|
||
|
|
serverNodes.forEach((node, index) => {
|
||
|
|
const x = LAYOUT_CONFIG.START_X + serverOffsetX + index * LAYOUT_CONFIG.NODE_SPACING;
|
||
|
|
const y = LAYOUT_CONFIG.START_Y + LAYOUT_CONFIG.TIER_SPACING;
|
||
|
|
|
||
|
|
layoutedNodes.push({
|
||
|
|
...node,
|
||
|
|
position: { x, y },
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
return {
|
||
|
|
nodes: layoutedNodes,
|
||
|
|
edges,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
export function applyGridLayout(
|
||
|
|
nodes: TopologyNode[],
|
||
|
|
edges: TopologyEdge[]
|
||
|
|
): { nodes: TopologyNode[]; edges: TopologyEdge[] } {
|
||
|
|
const columns = Math.ceil(Math.sqrt(nodes.length));
|
||
|
|
|
||
|
|
const layoutedNodes = nodes.map((node, index) => ({
|
||
|
|
...node,
|
||
|
|
position: {
|
||
|
|
x: LAYOUT_CONFIG.START_X + (index % columns) * LAYOUT_CONFIG.NODE_SPACING,
|
||
|
|
y: LAYOUT_CONFIG.START_Y + Math.floor(index / columns) * LAYOUT_CONFIG.TIER_SPACING,
|
||
|
|
},
|
||
|
|
}));
|
||
|
|
|
||
|
|
return {
|
||
|
|
nodes: layoutedNodes,
|
||
|
|
edges,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
export function layoutTopologyGraph(
|
||
|
|
nodes: TopologyNode[],
|
||
|
|
edges: TopologyEdge[]
|
||
|
|
): { nodes: TopologyNode[]; edges: TopologyEdge[] } {
|
||
|
|
if (nodes.length === 0) {
|
||
|
|
return { nodes: [], edges: [] };
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nodes.length < 20) {
|
||
|
|
return applyHierarchicalLayout(nodes, edges);
|
||
|
|
}
|
||
|
|
|
||
|
|
return applyGridLayout(nodes, edges);
|
||
|
|
}
|