dreamSongUtils.js
1 // Function to parse DreamSong.canvas data 2 export function parseDreamSongCanvas(canvasData) { 3 if (typeof canvasData !== 'object' || canvasData === null) { 4 return { nodes: [], edges: [] }; 5 } 6 return { 7 nodes: canvasData.nodes || [], 8 edges: canvasData.edges || [] 9 }; 10 } 11 12 // Function to perform topological sorting of nodes 13 export function topologicalSort(nodes, edges) { 14 const graph = new Map(); 15 const inDegree = new Map(); 16 17 // Initialize graph and in-degree 18 nodes.forEach(node => { 19 graph.set(node.id, []); 20 inDegree.set(node.id, 0); 21 }); 22 23 // Build graph and calculate in-degree 24 edges.forEach(edge => { 25 if (graph.has(edge.fromNode) && graph.has(edge.toNode)) { 26 graph.get(edge.fromNode).push(edge.toNode); 27 inDegree.set(edge.toNode, inDegree.get(edge.toNode) + 1); 28 } 29 }); 30 31 // Queue for nodes with no incoming edges 32 const queue = nodes.filter(node => inDegree.get(node.id) === 0).map(node => node.id); 33 const sortedNodes = []; 34 35 while (queue.length > 0) { 36 const nodeId = queue.shift(); 37 sortedNodes.push(nodes.find(node => node.id === nodeId)); 38 39 graph.get(nodeId).forEach(neighbor => { 40 inDegree.set(neighbor, inDegree.get(neighbor) - 1); 41 if (inDegree.get(neighbor) === 0) { 42 queue.push(neighbor); 43 } 44 }); 45 } 46 47 // Check for cycles 48 if (sortedNodes.length !== nodes.length) { 49 // Graph contains a cycle, but we'll return what we have 50 } 51 52 return sortedNodes; 53 } 54 55 // Function to process DreamSong data 56 export function processDreamSongData(canvasData) { 57 const { nodes, edges } = parseDreamSongCanvas(canvasData); 58 const sortedNodes = topologicalSort(nodes, edges); 59 return sortedNodes; 60 }