import GraphNode, { GraphNodeInterface } from './GraphNode'; import { NodeData } from './types'; type NodesList = Map, GraphNode>; interface GraphInterface { nodes: NodesList; addEdge( source: NodeData, destination: NodeData, edgeScore: number, ): ReadonlyArray>; addNode(data: NodeData): GraphNodeInterface; removeNode(data: NodeData): boolean | undefined; removeEdge( source: NodeData, destination: NodeData, ): ReadonlyArray | null | undefined>; } export default class Graph implements GraphInterface { constructor() { this.nodes = new Map(); } nodes: NodesList; addEdge( source: NodeData, destination: NodeData, edgeScore: number, ): ReadonlyArray> { const sourceNode = this.addNode(source); const destinationNode = this.addNode(destination); sourceNode.addEdge(destinationNode, edgeScore); return [sourceNode, destinationNode]; } addNode(data: NodeData): GraphNodeInterface { if (this.nodes.has(data)) { const nodeData = this.nodes.get(data); if (nodeData) { return nodeData; } } const node = new GraphNode(data); this.nodes.set(data, node); return node; } removeNode(data: NodeData): boolean | undefined { const current = this.nodes.get(data); if (current) { current.edges.forEach(({ node }) => { node.removeEdge(current); }); } return this.nodes.delete(data); } removeEdge( source: NodeData, destination: NodeData, ): ReadonlyArray | null | undefined> { const sourceNode = this.nodes.get(source); const destinationNode = this.nodes.get(destination); if (sourceNode && destinationNode) { sourceNode.removeEdge(destinationNode); } return [sourceNode, destinationNode]; } findLowestScore(startNode: NodeData): { lowestScore: number | null; lowestScoreNode: NodeData; } { // @ts-expect-error - TS7034 - Variable 'lowestScore' implicitly has type 'any' in some locations where its type cannot be determined. let lowestScore = null; let lowestScoreNode = startNode; const findLowestScoreRecursive = (node: GraphNodeInterface) => { node.getEdges().forEach((edge) => { const { score, node: edgeNode } = edge; // @ts-expect-error - TS7005 - Variable 'lowestScore' implicitly has an 'any' type. | TS7005 - Variable 'lowestScore' implicitly has an 'any' type. if (lowestScore === null || score < lowestScore) { lowestScore = score; lowestScoreNode = edgeNode.data; } findLowestScoreRecursive(edgeNode); }); }; const startGraphNode = this.nodes.get(startNode); if (startGraphNode) { findLowestScoreRecursive(startGraphNode); } return { lowestScore, lowestScoreNode }; } }