From 40f4c824fff3982b0e93263b56711b8c121e9731 Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Mon, 6 Nov 2023 17:42:17 +0100 Subject: [PATCH 01/19] Add GraphParamsContext for managing graph parameters as states --- .../src/GraphParamsContext.jsx | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 dijkstra-prim-visualization/src/GraphParamsContext.jsx diff --git a/dijkstra-prim-visualization/src/GraphParamsContext.jsx b/dijkstra-prim-visualization/src/GraphParamsContext.jsx new file mode 100644 index 0000000..10728c0 --- /dev/null +++ b/dijkstra-prim-visualization/src/GraphParamsContext.jsx @@ -0,0 +1,35 @@ +import PropTypes from "prop-types"; +import { createContext, useState } from "react"; + +export const GraphParamsContext = createContext(); + +// Custom hook useGraphParams to manage the states +const useGraphParams = () => { + const [nodePoints, setNodePoints] = useState([]); + const [edges, setEdges] = useState([]); + + return { nodePoints, setNodePoints, edges, setEdges }; +}; + +/** + * Provides the context for the graph parameters. + * @param {Object} props - The component props. + * @param {ReactNode} props.children - The child components to be rendered. + * @returns {JSX.Element} - The context provider component with the graph parameters as value. + */ +export const GraphParamsProvider = ({ children }) => { + // Get the graph parameters from the useGraphParams hook + const graphParams = useGraphParams(); + + // Return the context provider component with the graph parameters as value + return ( + + {children} + + ); +}; + +// Makes sure the 'children' prop is a React node and that it is a required parameter +GraphParamsProvider.propTypes = { + children: PropTypes.node.isRequired, +}; From 1d0dbf0e128187719b5fbcc5810511106659a8ed Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Mon, 6 Nov 2023 17:43:38 +0100 Subject: [PATCH 02/19] Add GraphParamsProvider to App.jsx --- dijkstra-prim-visualization/src/App.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dijkstra-prim-visualization/src/App.jsx b/dijkstra-prim-visualization/src/App.jsx index a691e5d..85c79e4 100644 --- a/dijkstra-prim-visualization/src/App.jsx +++ b/dijkstra-prim-visualization/src/App.jsx @@ -1,11 +1,12 @@ import "./App.css"; import Canvas from "./components/Canvas/Canvas"; +import { GraphParamsProvider } from "./GraphParamsContext"; function App() { return ( - <> + - + ); } From 678329502af037aaf1f72e0d30090fac3d994b73 Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Mon, 6 Nov 2023 17:44:12 +0100 Subject: [PATCH 03/19] Add GraphParamsContext to Canvas component --- .../src/components/Canvas/Canvas.jsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx b/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx index b289267..66a6c69 100644 --- a/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx +++ b/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx @@ -1,17 +1,18 @@ -import { useState, useRef } from "react"; +import { useState, useRef, useContext } from "react"; import classes from "./Canvas.module.css"; import Node from "./Node/Node"; import Edge from "./Edge/Edge"; import { newEdgeValid, newNodePositionValid } from "./CanvasUtils"; +import { GraphParamsContext } from "../../GraphParamsContext"; /** * Canvas component for visualizing nodes and edges. * @returns {JSX.Element} The Canvas component. */ const Canvas = () => { - // State variables to keep track of all nodes and edges - const [nodePoints, setNodePoints] = useState([]); - const [edges, setEdges] = useState([]); + // Destructure the states from context + const { nodePoints, setNodePoints, edges, setEdges } = + useContext(GraphParamsContext); // Object with default data to reset firstNode, when needed const resetNodeData = { @@ -99,9 +100,11 @@ const Canvas = () => { className={classes.canvas} onClick={canvasClickHandler} > + {/* Render all edges */} {edges.map((edge, index) => ( ))} + {/* Render all nodes */} {nodePoints.map((nodePoint, index) => ( Date: Mon, 6 Nov 2023 18:06:03 +0100 Subject: [PATCH 04/19] Add Navbar component with print buttons --- .../src/components/Navbar/Navbar.jsx | 26 +++++++++++++++++++ .../src/components/Navbar/Navbar.module.css | 1 + .../components/Navbar/Navbar.module.css.map | 1 + .../src/components/Navbar/Navbar.module.scss | 0 4 files changed, 28 insertions(+) create mode 100644 dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx create mode 100644 dijkstra-prim-visualization/src/components/Navbar/Navbar.module.css create mode 100644 dijkstra-prim-visualization/src/components/Navbar/Navbar.module.css.map create mode 100644 dijkstra-prim-visualization/src/components/Navbar/Navbar.module.scss diff --git a/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx b/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx new file mode 100644 index 0000000..f1b2610 --- /dev/null +++ b/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx @@ -0,0 +1,26 @@ +import { useContext } from "react"; +import { GraphParamsContext } from "../../GraphParamsContext"; + +const Navbar = () => { + const { nodePoints, edges } = useContext(GraphParamsContext); + return ( + <> + + + + ); +}; + +export default Navbar; diff --git a/dijkstra-prim-visualization/src/components/Navbar/Navbar.module.css b/dijkstra-prim-visualization/src/components/Navbar/Navbar.module.css new file mode 100644 index 0000000..e18b6bc --- /dev/null +++ b/dijkstra-prim-visualization/src/components/Navbar/Navbar.module.css @@ -0,0 +1 @@ +/*# sourceMappingURL=Navbar.module.css.map */ \ No newline at end of file diff --git a/dijkstra-prim-visualization/src/components/Navbar/Navbar.module.css.map b/dijkstra-prim-visualization/src/components/Navbar/Navbar.module.css.map new file mode 100644 index 0000000..37bd8f9 --- /dev/null +++ b/dijkstra-prim-visualization/src/components/Navbar/Navbar.module.css.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"names":[],"mappings":"","file":"Navbar.module.css"} \ No newline at end of file diff --git a/dijkstra-prim-visualization/src/components/Navbar/Navbar.module.scss b/dijkstra-prim-visualization/src/components/Navbar/Navbar.module.scss new file mode 100644 index 0000000..e69de29 From 6afe064f5e2a78c5305196d95cb1d534024a0538 Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Mon, 6 Nov 2023 18:06:10 +0100 Subject: [PATCH 05/19] Add Navbar component to App.jsx --- dijkstra-prim-visualization/src/App.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dijkstra-prim-visualization/src/App.jsx b/dijkstra-prim-visualization/src/App.jsx index 85c79e4..fab882f 100644 --- a/dijkstra-prim-visualization/src/App.jsx +++ b/dijkstra-prim-visualization/src/App.jsx @@ -1,10 +1,12 @@ import "./App.css"; import Canvas from "./components/Canvas/Canvas"; +import Navbar from "./components/Navbar/Navbar"; import { GraphParamsProvider } from "./GraphParamsContext"; function App() { return ( + ); From 6363016d75eddb6e9f630e6a2e5c9f2e75c6d8be Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Mon, 6 Nov 2023 18:12:48 +0100 Subject: [PATCH 06/19] Add a few lines of descriptive comment for doc. --- dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx b/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx index f1b2610..33bcae9 100644 --- a/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx +++ b/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx @@ -1,6 +1,10 @@ import { useContext } from "react"; import { GraphParamsContext } from "../../GraphParamsContext"; +/** + * Navbar component displays buttons to print nodePoints and edges. + * @returns {JSX.Element} Navbar component + */ const Navbar = () => { const { nodePoints, edges } = useContext(GraphParamsContext); return ( From 706fd8d6b68e5020a9c9d9843ec6d0ef14f18adc Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Thu, 9 Nov 2023 20:39:00 +0100 Subject: [PATCH 07/19] Refactor Edge component props to include id --- .../src/components/Canvas/Edge/Edge.jsx | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.jsx b/dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.jsx index 01f74e0..6b66a1e 100644 --- a/dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.jsx +++ b/dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.jsx @@ -2,20 +2,26 @@ import PropTypes from "prop-types"; import classes from "./Edge.module.css"; /** - * Renders a line connecting two points on the canvas. - * @param {number} x1 - The x-coordinate of the starting point. - * @param {number} y1 - The y-coordinate of the starting point. - * @param {number} x2 - The x-coordinate of the ending point. - * @param {number} y2 - The y-coordinate of the ending point. + * Renders an edge between two points on the canvas. + * @param {Object} props - The component props. + * @param {string} props.id - The unique identifier for the edge. + * @param {number} props.x1 - The x-coordinate of the starting point. + * @param {number} props.y1 - The y-coordinate of the starting point. + * @param {number} props.x2 - The x-coordinate of the ending point. + * @param {number} props.y2 - The y-coordinate of the ending point. + * @returns {JSX.Element} - The rendered component. */ -const Edge = ({ x1, y1, x2, y2 }) => { - return ; +const Edge = ({ id, x1, y1, x2, y2 }) => { + return ( + + ); }; export default Edge; // Validates that the required props are passed and their type is number Edge.propTypes = { + id: PropTypes.string.isRequired, x1: PropTypes.number.isRequired, y1: PropTypes.number.isRequired, x2: PropTypes.number.isRequired, From 47dcb5451723f61f0df9a0b6b875aeee4485e5ad Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Thu, 9 Nov 2023 20:48:57 +0100 Subject: [PATCH 08/19] Refactor Node component props to include id. --- .../src/components/Canvas/Node/Node.jsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dijkstra-prim-visualization/src/components/Canvas/Node/Node.jsx b/dijkstra-prim-visualization/src/components/Canvas/Node/Node.jsx index 8062ff6..3347b3f 100644 --- a/dijkstra-prim-visualization/src/components/Canvas/Node/Node.jsx +++ b/dijkstra-prim-visualization/src/components/Canvas/Node/Node.jsx @@ -2,19 +2,23 @@ import PropTypes from "prop-types"; import classes from "./Node.module.css"; /** - * A component that renders a circle representing a node on the canvas. - * @param {number} cx - The x-coordinate of the center of the circle. - * @param {number} cy - The y-coordinate of the center of the circle. - * @param {function} onNodeClick - A callback function to handle click events on the node. + * Renders a node on the canvas. + * @param {Object} props - The props object. + * @param {string} props.id - The id of the node. + * @param {number} props.cx - The x-coordinate of the node. + * @param {number} props.cy - The y-coordinate of the node. + * @param {function} props.onNodeClick - The function to call when the node is clicked. + * @returns {JSX.Element} - The node element. */ -const Node = ({ cx, cy, onNodeClick }) => { +const Node = ({ id, cx, cy, onNodeClick }) => { return ( onNodeClick(event, { x: cx, y: cy })} + onClick={(event) => onNodeClick(event, { id: id, x: cx, y: cy })} /> ); }; @@ -24,6 +28,7 @@ export default Node; // Ensures that the required props are passed and have the correct type Node.propTypes = { onNodeClick: PropTypes.func.isRequired, + id: PropTypes.string.isRequired, cx: PropTypes.number.isRequired, cy: PropTypes.number.isRequired, }; From d03d1db4fd97918f4416e7cd8cf2322186a85d13 Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Fri, 10 Nov 2023 00:21:51 +0100 Subject: [PATCH 09/19] Add IDs&weights to edges, and IDs to nodes --- .../src/components/Canvas/Canvas.jsx | 93 +++++++++++++------ 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx b/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx index 66a6c69..1b7374d 100644 --- a/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx +++ b/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx @@ -1,4 +1,4 @@ -import { useState, useRef, useContext } from "react"; +import React, { useState, useRef, useContext } from "react"; import classes from "./Canvas.module.css"; import Node from "./Node/Node"; import Edge from "./Edge/Edge"; @@ -7,6 +7,7 @@ import { GraphParamsContext } from "../../GraphParamsContext"; /** * Canvas component for visualizing nodes and edges. + * Handles user interactions for adding nodes and edges * @returns {JSX.Element} The Canvas component. */ const Canvas = () => { @@ -14,23 +15,28 @@ const Canvas = () => { const { nodePoints, setNodePoints, edges, setEdges } = useContext(GraphParamsContext); - // Object with default data to reset firstNode, when needed - const resetNodeData = { + // Object with default data to reset firstClickedNode, when needed + const resetFirstClickedNode = { isClicked: false, - x: null, - y: null, + node: null, }; // State variable to keep track of the first node clicked when creating an edge - const [firstNode, setFirstNode] = useState(resetNodeData); + const [firstClickedNode, setFirstClickedNode] = useState( + resetFirstClickedNode, + ); // Reference to the canvas SVG element const canvasRef = useRef(null); - // Handler function for when the canvas is clicked + /** + * Handler function for when the canvas is clicked. + * Adds a new node at the clicked position if the position is valid. + * @param {MouseEvent} event - The click event. + */ const canvasClickHandler = (event) => { - // Reset the firstNode state variable - setFirstNode(resetNodeData); + // Reset the firstClickedNode state variable + setFirstClickedNode(resetFirstClickedNode); // Calculate the coordinates of the clicked point relative to the canvas const nodePointAbsoluteX = event.clientX; @@ -42,6 +48,10 @@ const Canvas = () => { // Create a new node point object const newNodePoint = { + id: + String(nodePointCanvasRelativeX) + + ":" + + String(nodePointCanvasRelativeY), x: nodePointCanvasRelativeX, y: nodePointCanvasRelativeY, }; @@ -55,33 +65,46 @@ const Canvas = () => { setNodePoints((prevNodePoints) => [...prevNodePoints, newNodePoint]); }; - // Handler function for when a node is clicked - const nodeClickHandler = (event, points) => { + /** + * Handler function for when a node is clicked. + * Adds a new edge between the first and second nodes if a second node is clicked. + * Resets the first node if the same node is clicked again. + * @param {MouseEvent} event - The click event. + * @param {Object} node - The clicked node object. + */ + const nodeClickHandler = (event, node) => { event.stopPropagation(); // If no first node has been clicked yet, set the clicked node as the first node - if (firstNode.isClicked === false) { - setFirstNode({ isClicked: true, x: points.x, y: points.y }); + if (!firstClickedNode.isClicked) { + setFirstClickedNode({ isClicked: true, node: node }); } // If the same node is clicked again, reset the first node - else if (firstNode.x === points.x && firstNode.y === points.y) { - console.log("first node clicked again, reset firstNode"); - setFirstNode(resetNodeData); + else if ( + firstClickedNode.node.x === node.x && + firstClickedNode.node.y === node.y + ) { + console.log("first node clicked again, reset firstClickedNode"); + setFirstClickedNode(resetFirstClickedNode); } // If a different node is clicked, create a new edge between the first and second nodes else { - addEdge(firstNode, { x: points.x, y: points.y }); - setFirstNode(resetNodeData); + addEdge(firstClickedNode.node, node); + setFirstClickedNode(resetFirstClickedNode); } }; - // Function to add a new edge to the list of all edges + /** + * Function to add a new edge to the list of all edges. + * @param {Object} firstNode - The first node object. + * @param {Object} secondNode - The second node object. + */ const addEdge = (firstNode, secondNode) => { const newEdge = { - x1: firstNode.x, - y1: firstNode.y, - x2: secondNode.x, - y2: secondNode.y, + id: firstNode.id + "-" + secondNode.id, + weight: Math.floor(Math.random() * 100) + 1, + firstNode: firstNode, + secondNode: secondNode, }; // Check if the new edge is valid (not overlapping with existing edges) @@ -101,13 +124,29 @@ const Canvas = () => { onClick={canvasClickHandler} > {/* Render all edges */} - {edges.map((edge, index) => ( - + {edges.map((edge) => ( + + + + {edge.weight} + + ))} {/* Render all nodes */} - {nodePoints.map((nodePoint, index) => ( + {nodePoints.map((nodePoint) => ( Date: Fri, 10 Nov 2023 00:22:13 +0100 Subject: [PATCH 10/19] Refactored edge validation logic in CanvasUtils.js --- .../src/components/Canvas/CanvasUtils.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dijkstra-prim-visualization/src/components/Canvas/CanvasUtils.js b/dijkstra-prim-visualization/src/components/Canvas/CanvasUtils.js index 1c961fc..4e358c1 100644 --- a/dijkstra-prim-visualization/src/components/Canvas/CanvasUtils.js +++ b/dijkstra-prim-visualization/src/components/Canvas/CanvasUtils.js @@ -67,14 +67,14 @@ export const newNodePositionValid = (newNodePoint, nodePoints, canvasRef) => { export const newEdgeValid = (newEdge, edges) => { const edgeExists = edges.some( (edge) => - (edge.x1 === newEdge.x1 && - edge.y1 === newEdge.y1 && - edge.x2 === newEdge.x2 && - edge.y2 === newEdge.y2) || - (edge.x1 === newEdge.x2 && - edge.y1 === newEdge.y2 && - edge.x2 === newEdge.x1 && - edge.y2 === newEdge.y1), + (edge.firstNode.x === newEdge.firstNode.x && + edge.firstNode.y === newEdge.firstNode.y && + edge.secondNode.x === newEdge.secondNode.x && + edge.secondNode.y === newEdge.secondNode.y) || + (edge.firstNode.x === newEdge.secondNode.x && + edge.firstNode.y === newEdge.secondNode.y && + edge.secondNode.x === newEdge.firstNode.x && + edge.secondNode.y === newEdge.firstNode.y), ); if (edgeExists) { From 5becb7632f4d3b9575bae76d4692e66126b98b1d Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Fri, 10 Nov 2023 01:26:22 +0100 Subject: [PATCH 11/19] Refactor Canvas component to use Nodes and Edges components --- .../src/components/Canvas/Canvas.jsx | 128 ++++++------------ 1 file changed, 43 insertions(+), 85 deletions(-) diff --git a/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx b/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx index 1b7374d..49fb121 100644 --- a/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx +++ b/dijkstra-prim-visualization/src/components/Canvas/Canvas.jsx @@ -1,9 +1,11 @@ -import React, { useState, useRef, useContext } from "react"; +import { useState, useRef, useContext } from "react"; import classes from "./Canvas.module.css"; -import Node from "./Node/Node"; -import Edge from "./Edge/Edge"; import { newEdgeValid, newNodePositionValid } from "./CanvasUtils"; import { GraphParamsContext } from "../../GraphParamsContext"; +import Nodes from "./Nodes/Nodes"; +import Edges from "./Edges/Edges"; + +const MAX_EDGE_WEIGHT = 100; /** * Canvas component for visualizing nodes and edges. @@ -12,8 +14,7 @@ import { GraphParamsContext } from "../../GraphParamsContext"; */ const Canvas = () => { // Destructure the states from context - const { nodePoints, setNodePoints, edges, setEdges } = - useContext(GraphParamsContext); + const { nodes, setNodes, edges, setEdges } = useContext(GraphParamsContext); // Object with default data to reset firstClickedNode, when needed const resetFirstClickedNode = { @@ -21,7 +22,7 @@ const Canvas = () => { node: null, }; - // State variable to keep track of the first node clicked when creating an edge + // Initialize state to track the first clicked node const [firstClickedNode, setFirstClickedNode] = useState( resetFirstClickedNode, ); @@ -35,34 +36,28 @@ const Canvas = () => { * @param {MouseEvent} event - The click event. */ const canvasClickHandler = (event) => { - // Reset the firstClickedNode state variable setFirstClickedNode(resetFirstClickedNode); // Calculate the coordinates of the clicked point relative to the canvas - const nodePointAbsoluteX = event.clientX; - const nodePointAbsoluteY = event.clientY; - const nodePointCanvasRelativeX = - nodePointAbsoluteX - canvasRef.current.getBoundingClientRect().left; - const nodePointCanvasRelativeY = - nodePointAbsoluteY - canvasRef.current.getBoundingClientRect().top; - - // Create a new node point object - const newNodePoint = { - id: - String(nodePointCanvasRelativeX) + - ":" + - String(nodePointCanvasRelativeY), - x: nodePointCanvasRelativeX, - y: nodePointCanvasRelativeY, + const nodeAbsoluteX = event.clientX; + const nodeAbsoluteY = event.clientY; + const nodeCanvasRelativeX = + nodeAbsoluteX - canvasRef.current.getBoundingClientRect().left; + const nodeCanvasRelativeY = + nodeAbsoluteY - canvasRef.current.getBoundingClientRect().top; + + const newNode = { + id: `${nodeCanvasRelativeX}:${nodeCanvasRelativeY}`, + x: nodeCanvasRelativeX, + y: nodeCanvasRelativeY, }; // Check if the new node position is valid (not overlapping with existing nodes) - if (!newNodePositionValid(newNodePoint, nodePoints, canvasRef)) { + if (!newNodePositionValid(newNode, nodes, canvasRef)) { return; } - // Add the new node point to the list of all nodes - setNodePoints((prevNodePoints) => [...prevNodePoints, newNodePoint]); + setNodes((prevNodes) => [...prevNodes, newNode]); }; /** @@ -75,83 +70,46 @@ const Canvas = () => { const nodeClickHandler = (event, node) => { event.stopPropagation(); - // If no first node has been clicked yet, set the clicked node as the first node + const addEdge = (firstNode, secondNode) => { + const newEdge = { + id: `${firstNode.id}-${secondNode.id}`, + weight: Math.floor(Math.random() * MAX_EDGE_WEIGHT) + 1, + firstNode: firstNode, + secondNode: secondNode, + }; + + if (!newEdgeValid(newEdge, edges)) { + return; + } + + setEdges((prevEdges) => [...prevEdges, newEdge]); + }; + if (!firstClickedNode.isClicked) { + // If no node has been clicked yet, set the current node as the first clicked node setFirstClickedNode({ isClicked: true, node: node }); - } - // If the same node is clicked again, reset the first node - else if ( + } else if ( firstClickedNode.node.x === node.x && firstClickedNode.node.y === node.y ) { - console.log("first node clicked again, reset firstClickedNode"); + // If the same node is clicked again, reset the first clicked node + console.log("same node clicked again, reset the first clicked node"); setFirstClickedNode(resetFirstClickedNode); - } - // If a different node is clicked, create a new edge between the first and second nodes - else { + } else { + // If a different node is clicked, add an edge and reset the first clicked node addEdge(firstClickedNode.node, node); setFirstClickedNode(resetFirstClickedNode); } }; - /** - * Function to add a new edge to the list of all edges. - * @param {Object} firstNode - The first node object. - * @param {Object} secondNode - The second node object. - */ - const addEdge = (firstNode, secondNode) => { - const newEdge = { - id: firstNode.id + "-" + secondNode.id, - weight: Math.floor(Math.random() * 100) + 1, - firstNode: firstNode, - secondNode: secondNode, - }; - - // Check if the new edge is valid (not overlapping with existing edges) - if (!newEdgeValid(newEdge, edges)) { - return; - } - - // Add the new edge to the list of all edges - setEdges((prevEdges) => [...prevEdges, newEdge]); - }; - - // Render the canvas SVG element with all nodes and edges return ( - {/* Render all edges */} - {edges.map((edge) => ( - - - - {edge.weight} - - - ))} - {/* Render all nodes */} - {nodePoints.map((nodePoint) => ( - - ))} + + ); }; From 7ff32cd825dd8ca87eaa34432c49da28ad31758e Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Fri, 10 Nov 2023 01:26:38 +0100 Subject: [PATCH 12/19] Refactor useGraphParams hook to use "nodes" instead of "nodePoints" --- dijkstra-prim-visualization/src/GraphParamsContext.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dijkstra-prim-visualization/src/GraphParamsContext.jsx b/dijkstra-prim-visualization/src/GraphParamsContext.jsx index 10728c0..b5cca0c 100644 --- a/dijkstra-prim-visualization/src/GraphParamsContext.jsx +++ b/dijkstra-prim-visualization/src/GraphParamsContext.jsx @@ -5,10 +5,10 @@ export const GraphParamsContext = createContext(); // Custom hook useGraphParams to manage the states const useGraphParams = () => { - const [nodePoints, setNodePoints] = useState([]); + const [nodes, setNodes] = useState([]); const [edges, setEdges] = useState([]); - return { nodePoints, setNodePoints, edges, setEdges }; + return { nodes, setNodes, edges, setEdges }; }; /** From 11682a383ba76aae4dbdc5215f71bdb5836e2946 Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Fri, 10 Nov 2023 01:26:59 +0100 Subject: [PATCH 13/19] Refactor node position validation functions in CanvasUtils.js --- .../src/components/Canvas/CanvasUtils.js | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/dijkstra-prim-visualization/src/components/Canvas/CanvasUtils.js b/dijkstra-prim-visualization/src/components/Canvas/CanvasUtils.js index 4e358c1..1cf4cce 100644 --- a/dijkstra-prim-visualization/src/components/Canvas/CanvasUtils.js +++ b/dijkstra-prim-visualization/src/components/Canvas/CanvasUtils.js @@ -1,14 +1,14 @@ /** * Calculates the Euclidean distance between two points. - * @param {Object} existingNodePoint - The coordinates of an existing node. - * @param {Object} newNodePoint - The coordinates of a new node. + * @param {Object} existingNode - The coordinates of an existing node. + * @param {Object} newNode - The coordinates of a new node. * @returns {boolean} - Returns true if the distance is less than or equal to 35px, false otherwise. */ -const isTooCloseToExistingNode = (existingNodePoint, newNodePoint) => { - const x1 = existingNodePoint.x; - const y1 = existingNodePoint.y; - const x2 = newNodePoint.x; - const y2 = newNodePoint.y; +const isTooCloseToExistingNode = (existingNode, newNode) => { + const x1 = existingNode.x; + const y1 = existingNode.y; + const x2 = newNode.x; + const y2 = newNode.y; const distance = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); @@ -17,30 +17,30 @@ const isTooCloseToExistingNode = (existingNodePoint, newNodePoint) => { /** * Checks if a new node is within the bounds of the canvas. - * @param {Object} newNodePoint - The coordinates of the new node. + * @param {Object} newNode - The coordinates of the new node. * @param {number} nodeRadius - The radius of the node. * @param {Object} canvasRef - A reference to the canvas element. * @returns {boolean} - Returns true if the new node is within the bounds of the canvas, false otherwise. */ -const isNodeInBounds = (newNodePoint, nodeRadius, canvasRef) => { +const isNodeInBounds = (newNode, nodeRadius, canvasRef) => { return ( - newNodePoint.x - nodeRadius >= 0 && - newNodePoint.y - nodeRadius >= 0 && - newNodePoint.x + nodeRadius <= canvasRef.current.clientWidth && - newNodePoint.y + nodeRadius <= canvasRef.current.clientHeight + newNode.x - nodeRadius >= 0 && + newNode.y - nodeRadius >= 0 && + newNode.x + nodeRadius <= canvasRef.current.clientWidth && + newNode.y + nodeRadius <= canvasRef.current.clientHeight ); }; /** * Checks if a new node position is valid. - * @param {Object} newNodePoint - The coordinates of the new node. - * @param {Array} nodePoints - An array of existing node coordinates. + * @param {Object} newNode - The coordinates of the new node. + * @param {Array} nodes - An array of existing node coordinates. * @param {Object} canvasRef - A reference to the canvas element. * @returns {boolean} - Returns true if the new node position is valid, false otherwise. */ -export const newNodePositionValid = (newNodePoint, nodePoints, canvasRef) => { - const isTooClose = nodePoints.some((existingNodePoint) => - isTooCloseToExistingNode(existingNodePoint, newNodePoint), +export const newNodePositionValid = (newNode, nodes, canvasRef) => { + const isTooClose = nodes.some((existingNode) => + isTooCloseToExistingNode(existingNode, newNode), ); if (isTooClose) { @@ -48,7 +48,7 @@ export const newNodePositionValid = (newNodePoint, nodePoints, canvasRef) => { return false; } - const isOutOfBounds = !isNodeInBounds(newNodePoint, 14, canvasRef); + const isOutOfBounds = !isNodeInBounds(newNode, 14, canvasRef); if (isOutOfBounds) { console.log("New node is out of bounds."); From 889b308a47e7fbb934275c7aad0933264b6d2917 Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Fri, 10 Nov 2023 01:28:18 +0100 Subject: [PATCH 14/19] Edge folder moved to Edges folder --- .../src/components/Canvas/{ => Edges}/Edge/Edge.jsx | 0 .../src/components/Canvas/{ => Edges}/Edge/Edge.module.css | 0 .../src/components/Canvas/{ => Edges}/Edge/Edge.module.css.map | 0 .../src/components/Canvas/{ => Edges}/Edge/Edge.module.scss | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename dijkstra-prim-visualization/src/components/Canvas/{ => Edges}/Edge/Edge.jsx (100%) rename dijkstra-prim-visualization/src/components/Canvas/{ => Edges}/Edge/Edge.module.css (100%) rename dijkstra-prim-visualization/src/components/Canvas/{ => Edges}/Edge/Edge.module.css.map (100%) rename dijkstra-prim-visualization/src/components/Canvas/{ => Edges}/Edge/Edge.module.scss (100%) diff --git a/dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.jsx b/dijkstra-prim-visualization/src/components/Canvas/Edges/Edge/Edge.jsx similarity index 100% rename from dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.jsx rename to dijkstra-prim-visualization/src/components/Canvas/Edges/Edge/Edge.jsx diff --git a/dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.module.css b/dijkstra-prim-visualization/src/components/Canvas/Edges/Edge/Edge.module.css similarity index 100% rename from dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.module.css rename to dijkstra-prim-visualization/src/components/Canvas/Edges/Edge/Edge.module.css diff --git a/dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.module.css.map b/dijkstra-prim-visualization/src/components/Canvas/Edges/Edge/Edge.module.css.map similarity index 100% rename from dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.module.css.map rename to dijkstra-prim-visualization/src/components/Canvas/Edges/Edge/Edge.module.css.map diff --git a/dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.module.scss b/dijkstra-prim-visualization/src/components/Canvas/Edges/Edge/Edge.module.scss similarity index 100% rename from dijkstra-prim-visualization/src/components/Canvas/Edge/Edge.module.scss rename to dijkstra-prim-visualization/src/components/Canvas/Edges/Edge/Edge.module.scss From eccac45032b43a69dc1fd0d2751aba4e0713bcae Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Fri, 10 Nov 2023 01:29:00 +0100 Subject: [PATCH 15/19] Node folder moved to Nodes folder --- .../src/components/Canvas/{ => Nodes}/Node/Node.jsx | 0 .../src/components/Canvas/{ => Nodes}/Node/Node.module.css | 0 .../src/components/Canvas/{ => Nodes}/Node/Node.module.css.map | 0 .../src/components/Canvas/{ => Nodes}/Node/Node.module.scss | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename dijkstra-prim-visualization/src/components/Canvas/{ => Nodes}/Node/Node.jsx (100%) rename dijkstra-prim-visualization/src/components/Canvas/{ => Nodes}/Node/Node.module.css (100%) rename dijkstra-prim-visualization/src/components/Canvas/{ => Nodes}/Node/Node.module.css.map (100%) rename dijkstra-prim-visualization/src/components/Canvas/{ => Nodes}/Node/Node.module.scss (100%) diff --git a/dijkstra-prim-visualization/src/components/Canvas/Node/Node.jsx b/dijkstra-prim-visualization/src/components/Canvas/Nodes/Node/Node.jsx similarity index 100% rename from dijkstra-prim-visualization/src/components/Canvas/Node/Node.jsx rename to dijkstra-prim-visualization/src/components/Canvas/Nodes/Node/Node.jsx diff --git a/dijkstra-prim-visualization/src/components/Canvas/Node/Node.module.css b/dijkstra-prim-visualization/src/components/Canvas/Nodes/Node/Node.module.css similarity index 100% rename from dijkstra-prim-visualization/src/components/Canvas/Node/Node.module.css rename to dijkstra-prim-visualization/src/components/Canvas/Nodes/Node/Node.module.css diff --git a/dijkstra-prim-visualization/src/components/Canvas/Node/Node.module.css.map b/dijkstra-prim-visualization/src/components/Canvas/Nodes/Node/Node.module.css.map similarity index 100% rename from dijkstra-prim-visualization/src/components/Canvas/Node/Node.module.css.map rename to dijkstra-prim-visualization/src/components/Canvas/Nodes/Node/Node.module.css.map diff --git a/dijkstra-prim-visualization/src/components/Canvas/Node/Node.module.scss b/dijkstra-prim-visualization/src/components/Canvas/Nodes/Node/Node.module.scss similarity index 100% rename from dijkstra-prim-visualization/src/components/Canvas/Node/Node.module.scss rename to dijkstra-prim-visualization/src/components/Canvas/Nodes/Node/Node.module.scss From 0600a860477fcff315724170622534859e7a03af Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Fri, 10 Nov 2023 01:29:21 +0100 Subject: [PATCH 16/19] Add Edges component for rendering edges on canvas --- .../src/components/Canvas/Edges/Edges.jsx | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 dijkstra-prim-visualization/src/components/Canvas/Edges/Edges.jsx diff --git a/dijkstra-prim-visualization/src/components/Canvas/Edges/Edges.jsx b/dijkstra-prim-visualization/src/components/Canvas/Edges/Edges.jsx new file mode 100644 index 0000000..f52eaaa --- /dev/null +++ b/dijkstra-prim-visualization/src/components/Canvas/Edges/Edges.jsx @@ -0,0 +1,54 @@ +import PropTypes from "prop-types"; +import React from "react"; +import Edge from "./Edge/Edge"; + +/** + * Renders edges on the canvas. + * @param {Object[]} edges - An array of edge objects. + * @param {string} edges[].id - The unique identifier of the edge. + * @param {Object} edges[].firstNode - The first node of the edge. + * @param {number} edges[].firstNode.x - The x-coordinate of the first node. + * @param {number} edges[].firstNode.y - The y-coordinate of the first node. + * @param {Object} edges[].secondNode - The second node of the edge. + * @param {number} edges[].secondNode.x - The x-coordinate of the second node. + * @param {number} edges[].secondNode.y - The y-coordinate of the second node. + * @param {number} edges[].weight - The weight of the edge. + * @returns {JSX.Element} - The rendered edges and their weights. + */ +const Edges = ({ edges }) => { + return ( + <> + {edges.map((edge) => ( + + + + {edge.weight} + + + ))} + + ); +}; + +export default Edges; + +Edges.propTypes = { + edges: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + weight: PropTypes.number.isRequired, + firstNode: PropTypes.object.isRequired, + secondNode: PropTypes.object.isRequired, + }), + ).isRequired, +}; From 887ef872e92d57f713999972faf65e0a97cd0a25 Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Fri, 10 Nov 2023 01:29:28 +0100 Subject: [PATCH 17/19] Add Nodes component for rendering list of nodes on canvas --- .../src/components/Canvas/Nodes/Nodes.jsx | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 dijkstra-prim-visualization/src/components/Canvas/Nodes/Nodes.jsx diff --git a/dijkstra-prim-visualization/src/components/Canvas/Nodes/Nodes.jsx b/dijkstra-prim-visualization/src/components/Canvas/Nodes/Nodes.jsx new file mode 100644 index 0000000..52edaba --- /dev/null +++ b/dijkstra-prim-visualization/src/components/Canvas/Nodes/Nodes.jsx @@ -0,0 +1,32 @@ +import PropTypes from "prop-types"; +import Node from "./Node/Node"; + +/** + * Renders a list of nodes on the canvas. + * @param {Object[]} nodes - An array of node objects. + * @param {string} nodes[].id - The unique identifier of the node. + * @param {number} nodes[].x - The x-coordinate of the node. + * @param {number} nodes[].y - The y-coordinate of the node. + * @param {function} onNodeClick - A callback function to handle node click events. + * @returns {JSX.Element} - A list of Node components. + */ +const Nodes = ({ nodes, onNodeClick }) => ( + <> + {nodes.map((node) => ( + + ))} + +); + +export default Nodes; + +Nodes.propTypes = { + nodes: PropTypes.array.isRequired, + onNodeClick: PropTypes.func.isRequired, +}; From b2e9fc7f2b3b47773267124a4d93278dbb8f3f9f Mon Sep 17 00:00:00 2001 From: Adilet Baimyrza uulu Date: Fri, 10 Nov 2023 01:29:38 +0100 Subject: [PATCH 18/19] Update Navbar component to display nodes instead of nodePoints --- .../src/components/Navbar/Navbar.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx b/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx index 33bcae9..6517ecf 100644 --- a/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx +++ b/dijkstra-prim-visualization/src/components/Navbar/Navbar.jsx @@ -2,19 +2,19 @@ import { useContext } from "react"; import { GraphParamsContext } from "../../GraphParamsContext"; /** - * Navbar component displays buttons to print nodePoints and edges. + * Navbar component displays buttons to print nodes and edges. * @returns {JSX.Element} Navbar component */ const Navbar = () => { - const { nodePoints, edges } = useContext(GraphParamsContext); + const { nodes, edges } = useContext(GraphParamsContext); return ( <>