We are looking for a way to map a reactflow diagram to a flat plaintext style. The tricky part is to capture the decision functionality, especially the part where the paths connect. The whole system is similar to dialogue game engine where one decision can lead to another but in the end they can all lead to the same ending.
A quick illustration:
B
a -> { } -> D
C
Should produce such text:
A
// Decision: node_3
B
// Decision end: node_3
// Decision: node_4
C
// Decision end: node_4
D
I've created a stackblitz example that shows the problem, it contains example input data but of course the chart can be expanded. I believe the example data to be complete, i.e. if the solution can handle this data it can handle any data.
https://stackblitz.com/edit/vitejs-vite-xlcdmc
The function that does the transformation can be found here:
components/Toolbar.tsx::handleExportComments
The desired output should look like this:
intro
intro 2
// Decision: node_3
fruits
// Decision: node_4
apple
// Decision end: node_4
// Decision: node_5
banana
// Decision end: node_5
fruit shake
// Decision end: node_3
// Decision: node_6
vegetables
// Decision: node_7
onion
// Decision end: node_7
// Decision: node_8
lettuce
lettuce with jogurt
// Decision end: node_8
salad
// Decision end: node_6
middle1
middle2
// Decision: node_14
top
// Decision end: node_14
// Decision: node_15
bottom
// Decision end: node_15
pre-ending
end
My current solution produces duplicates and seems to be plain out wrong when when we have multiple divergences.
It seems all the data to produce this is available, i.e. we have all the Edges (connections) and Nodes, could this be used somehow?
Functionality notes:
I have a suspicion this is a known math / CS problem but I hope there is a solution to this :)
I'm open to use a different tool but I need to have the ability to expand this with more fields.
Lastly, if you don't want / can't solve the issue even pointing me in the right direction or naming the problem so that I can google it better will be helpful.
I had to abruplty end working on that project and unfortunately I did not manage to implement this functionality in it's entirety. For what it's worth It seems I did manage to crack the problem in the end:
const nodes = {
intro: {
parents: [],
children: ["fruit", "vegetables"],
},
fruit: {
parents: ["intro"],
children: ["apple", "orange"],
},
apple: {
parents: ["fruit"],
children: ["fruit_mix"],
},
orange: {
parents: ["fruit"],
children: ["fruit_mix"],
},
fruit_mix: {
parents: ["apple", "orange"],
children: ["middle1"],
},
vegetables: {
parents: ["intro"],
children: ["carrot", "lettuce"],
},
carrot: {
parents: ["vegetables"],
children: ["middle1"],
},
lettuce: {
parents: ["vegetables"],
children: ["lettucejogurt"],
},
lettucejogurt: {
parents: ["lettuce"],
children: ["middle1"],
},
middle1: {
parents: ["lettuce", "carrot"],
children: ["middle2"],
},
middle2: {
parents: ["middle1"],
children: ["up", "down"],
},
up: {
parents: ["middle2"],
children: ["end"],
},
down: {
parents: ["middle2"],
children: ["end"],
},
end: {
parents: ["up", "down"],
children: [],
},
};
function exportComments() {
const output = [];
const visited = new Set();
function visit(nodeId) {
if (visited.has(nodeId)) {
return;
}
visited.add(nodeId);
// Add the current node to the output before visiting its children
output.push(nodeId);
const node = nodes[nodeId];
// Visit all children
node.children.forEach((childId) => {
// Only visit the child if all its parents have been visited
if (nodes[childId].parents.every((parentId) => visited.has(parentId))) {
visit(childId);
}
});
}
// Start traversal from the "intro" node
visit("intro");
console.log("output", output);
}
exportComments();
The code got really simplified and the main logic change is to check if a node has been visited or not.