-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(gsoc'24): Added helpful functions for debugging of circuit (#3870) #366
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe changes to the Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Scope
participant LocalStorage
participant JSONHandler
User->>Scope: Load Circuit
Scope->>JSONHandler: loadCircuit(data)
JSONHandler-->>Scope: Circuit Data Loaded
Scope->>LocalStorage: previous()
LocalStorage-->>Scope: Last autosaved circuit retrieved
Scope->>Scope: detectCycle()
Scope->>Scope: highlightNodes(array)
Scope-->>User: Circuit Updated with Cycle Highlighting
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configuration File (
|
✅ Deploy Preview for circuitverse ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- src/simulator/src/circuit.ts (2 hunks)
Additional comments not posted (2)
src/simulator/src/circuit.ts (2)
520-527
: LGTM!The code changes are approved.
634-646
: LGTM!The code changes are approved.
detectCycle() { | ||
const obj = {}; | ||
const result = []; | ||
|
||
for (let i = 0; i < globalScope.allNodes.length; i++) { | ||
const nodeId = globalScope.allNodes[i].id; | ||
for (let j = 0; j < globalScope.allNodes[i].connections.length; j++) { | ||
const connection = globalScope.allNodes[i].connections[j].id; | ||
if (obj[nodeId]) { | ||
obj[nodeId].push(connection); | ||
} else { | ||
obj[nodeId] = [connection]; | ||
} | ||
} | ||
} | ||
|
||
const newNestedArray = []; | ||
const singleConnectionNodes = []; | ||
|
||
for (const node in obj) { | ||
const connections = obj[node]; | ||
if (connections.length === 1) { | ||
singleConnectionNodes.push(node); | ||
} | ||
if (!isVisited(newNestedArray.flat(), node)) { | ||
const connectedNodes = [node]; | ||
exploreNodes(obj, node, newNestedArray.flat(), connectedNodes); | ||
newNestedArray.push(connectedNodes); | ||
} | ||
} | ||
|
||
for (let i = 0; i < singleConnectionNodes.length - 1; i++) { | ||
for (let j = i + 1; j < singleConnectionNodes.length; j++) { | ||
if (areElementsInSameNode(newNestedArray, singleConnectionNodes[i], singleConnectionNodes[j])) { | ||
const val1 = this.findNodeIndexById(singleConnectionNodes[i]); | ||
const val2 = this.findNodeIndexById(singleConnectionNodes[j]); | ||
if (globalScope.allNodes[val1].parent === globalScope.allNodes[val2].parent) { | ||
result.push(dfs(obj, singleConnectionNodes[i], singleConnectionNodes[j])); | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Function to check whether a node is already visited | ||
function isVisited(visited, node) { | ||
return visited.includes(node); | ||
} | ||
|
||
// Function to explore interconnected nodes | ||
function exploreNodes(graph, startNode, visited, connectedNodes) { | ||
visited.push(startNode); | ||
if (graph[startNode]) { | ||
for (let i = 0; i < graph[startNode].length; i++) { | ||
const connectedNode = graph[startNode][i]; | ||
if (!isVisited(visited, connectedNode)) { | ||
connectedNodes.push(connectedNode); | ||
exploreNodes(graph, connectedNode, visited, connectedNodes); | ||
} | ||
} | ||
} | ||
} | ||
|
||
function areElementsInSameNode(nestedArray, element1, element2) { | ||
for (const node of nestedArray) { | ||
if (node.includes(element1) && node.includes(element2)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
// Function to locate the nodes present between two specified nodes | ||
function dfs(graph, start, end, path = []) { | ||
if (start === end) { | ||
path.push(end); | ||
return path; | ||
} | ||
path.push(start); | ||
for (const neighbor of graph[start]) { | ||
if (!path.includes(neighbor)) { | ||
const newPath = dfs(graph, neighbor, end, path); | ||
if (newPath) { | ||
return newPath; | ||
} | ||
} | ||
} | ||
path.pop(); | ||
return []; | ||
} | ||
|
||
if (result.length) { | ||
this.highlightNodes(result); | ||
return result; | ||
} | ||
|
||
return 'No cycle found'; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor detectCycle
for readability and maintainability.
- Move nested helper functions outside to improve readability.
- Avoid using
globalScope
within the function by passing it as a parameter. - Add comments explaining the logic.
Apply this diff to refactor the function:
+ // Helper function to check whether a node is already visited
+ function isVisited(visited, node) {
+ return visited.includes(node);
+ }
+
+ // Helper function to explore interconnected nodes
+ function exploreNodes(graph, startNode, visited, connectedNodes) {
+ visited.push(startNode);
+ if (graph[startNode]) {
+ for (let i = 0; i < graph[startNode].length; i++) {
+ const connectedNode = graph[startNode][i];
+ if (!isVisited(visited, connectedNode)) {
+ connectedNodes.push(connectedNode);
+ exploreNodes(graph, connectedNode, visited, connectedNodes);
+ }
+ }
+ }
+ }
+
+ // Helper function to check if elements are in the same node
+ function areElementsInSameNode(nestedArray, element1, element2) {
+ for (const node of nestedArray) {
+ if (node.includes(element1) && node.includes(element2)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Helper function to locate the nodes present between two specified nodes
+ function dfs(graph, start, end, path = []) {
+ if (start === end) {
+ path.push(end);
+ return path;
+ }
+ path.push(start);
+ for (const neighbor of graph[start]) {
+ if (!path.includes(neighbor)) {
+ const newPath = dfs(graph, neighbor, end, path);
+ if (newPath) {
+ return newPath;
+ }
+ }
+ }
+ path.pop();
+ return [];
+ }
detectCycle() {
const obj = {};
const result = [];
for (let i = 0; i < globalScope.allNodes.length; i++) {
const nodeId = globalScope.allNodes[i].id;
for (let j = 0; j < globalScope.allNodes[i].connections.length; j++) {
const connection = globalScope.allNodes[i].connections[j].id;
if (obj[nodeId]) {
obj[nodeId].push(connection);
} else {
obj[nodeId] = [connection];
}
}
}
const newNestedArray = [];
const singleConnectionNodes = [];
for (const node in obj) {
const connections = obj[node];
if (connections.length === 1) {
singleConnectionNodes.push(node);
}
if (!isVisited(newNestedArray.flat(), node)) {
const connectedNodes = [node];
exploreNodes(obj, node, newNestedArray.flat(), connectedNodes);
newNestedArray.push(connectedNodes);
}
}
for (let i = 0; i < singleConnectionNodes.length - 1; i++) {
for (let j = i + 1; j < singleConnectionNodes.length; j++) {
if (areElementsInSameNode(newNestedArray, singleConnectionNodes[i], singleConnectionNodes[j])) {
const val1 = this.findNodeIndexById(singleConnectionNodes[i]);
const val2 = this.findNodeIndexById(singleConnectionNodes[j]);
if (globalScope.allNodes[val1].parent === globalScope.allNodes[val2].parent) {
result.push(dfs(obj, singleConnectionNodes[i], singleConnectionNodes[j]));
}
}
}
}
if (result.length) {
this.highlightNodes(result);
return result;
}
return 'No cycle found';
}
Committable suggestion was skipped due to low confidence.
loadCircuit(data: JSON) { | ||
if (data) { | ||
load(data); | ||
} else { | ||
alert('Invalid data'); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve error handling in loadCircuit
.
Using alert
for error handling is not user-friendly. Consider using a more user-friendly approach, such as displaying a message in the UI.
Apply this diff to improve error handling:
- alert('Invalid data');
+ // Replace this with a more user-friendly error handling approach
+ showMessage('Invalid data', 'error');
Committable suggestion was skipped due to low confidence.
findNodeIndexById(nodeId: string) { | ||
for (let i = 0; i < globalScope.allNodes.length; i++) { | ||
if (globalScope.allNodes[i].id === nodeId) { | ||
return i; | ||
} | ||
} | ||
return 'Not found'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure consistent return type in findNodeIndexById
.
The function should return a consistent type. Instead of returning a string 'Not found', consider returning -1
to indicate that the node was not found.
Apply this diff to ensure a consistent return type:
- return 'Not found';
+ return -1;
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
findNodeIndexById(nodeId: string) { | |
for (let i = 0; i < globalScope.allNodes.length; i++) { | |
if (globalScope.allNodes[i].id === nodeId) { | |
return i; | |
} | |
} | |
return 'Not found'; | |
findNodeIndexById(nodeId: string) { | |
for (let i = 0; i < globalScope.allNodes.length; i++) { | |
if (globalScope.allNodes[i].id === nodeId) { | |
return i; | |
} | |
} | |
return -1; |
Fixes #112
Stability improvements
ref PR - #3870
Summary by CodeRabbit