diff --git a/src/components/dsa/ContributorsSection.jsx b/src/components/dsa/ContributorsSection.jsx index 3237e69..52f3935 100644 --- a/src/components/dsa/ContributorsSection.jsx +++ b/src/components/dsa/ContributorsSection.jsx @@ -12,9 +12,9 @@ const ContributorsSection = ({ darkMode }) => {
-

Contributors to this page

+

Contributors to this page

- +
{dsaContributors.map((contributor, index) => ( {
- {contributor.name}
- -

{contributor.name}

-

{contributor.role}

- - - - -
- - - + + +
@@ -377,9 +454,9 @@ const GraphVisualizer = ({ algorithmName, isPlaying, setIsPlaying, speed, onFini const end = nodes.find(n => n.id === edge.to); if (!start || !end) return null; const isActive = visualState.activeLink && ((visualState.activeLink.from === edge.from && visualState.activeLink.to === edge.to) || (!isDirected && visualState.activeLink.from === edge.to && visualState.activeLink.to === edge.from)); - return ( {isWeighted && ({edge.weight})}); + return ({isWeighted && ({edge.weight})}); })} - {editMode === 'add-edge' && edgeStartNode !== null && (() => { const start = nodes.find(n => n.id === edgeStartNode); if(start) return ; return null; })()} + {editMode === 'add-edge' && edgeStartNode !== null && (() => { const start = nodes.find(n => n.id === edgeStartNode); if (start) return ; return null; })()} {nodes.map((node) => { const isStart = node.id === startNode; const isEnd = node.id === endNode; @@ -398,48 +475,51 @@ const GraphVisualizer = ({ algorithmName, isPlaying, setIsPlaying, speed, onFini const DsaVisualization = () => { const { toast } = useToast(); + const [sortingAlgorithms, setSortingAlgorithms] = useState(['BubbleSort']); + const [finishedCount, setFinishedCount] = useState(0); + + // Keep legacy state for non-sorting tabs + const [algorithm, setAlgorithm] = useState('BFS'); + const [activeTab, setActiveTab] = useState('sorting'); - const [algorithm, setAlgorithm] = useState('BubbleSort'); - const [secondAlgorithm, setSecondAlgorithm] = useState('QuickSort'); - const [arraySize, setArraySize] = useState(20); + const [arraySize, setArraySize] = useState(20); const [speed, setSpeed] = useState(50); const [isPlaying, setIsPlaying] = useState(false); const [isComparisonMode, setIsComparisonMode] = useState(false); const [darkMode, setDarkMode] = useState(true); const [customInput, setCustomInput] = useState(''); - const [searchTarget, setSearchTarget] = useState(42); // Default target - + const [searchTarget, setSearchTarget] = useState(42); const [array, setArray] = useState([]); - useEffect(() => { - if (activeTab === 'sorting' || activeTab === 'searching') { - resetArray(); - } - }, [arraySize, activeTab]); + // Independent effect for sortingAlgorithms initialization if needed, + // but we initialized it with default ['BubbleSort']. - const resetArray = () => { + // Helper for algo options (moved inside or kept outside if static, assuming it was static or defined inside) + const algoOptions = { + sorting: ['BubbleSort', 'SelectionSort', 'InsertionSort', 'MergeSort', 'QuickSort'], + searching: ['BinarySearch', 'LinearSearch'], + graphs: ['BFS', 'DFS', 'Dijkstra', 'AStar'], + linkedlist: [], + trees: [], + heaps: [], + dp: [] + }; + + const getBarColor = (isDark) => isDark ? 'rgba(148, 163, 184, 0.5)' : '#64748b'; + + const resetArray = useCallback(() => { setIsPlaying(false); - // If binary search, we should ideally sort, but random is fine for linear. - // To keep it simple, we generate random. - // If user selects BinarySearch, we might want to auto-sort or let them visualize fail/sort. + setFinishedCount(0); const newArr = Array.from({ length: arraySize }, () => Math.floor(Math.random() * 100) + 5); - - // If searching, ensure the target is present randomly 50% of the time for fun, or just random. - // Let's just keep random. setArray(newArr); + + // Reset bar styles const bars = document.querySelectorAll('[class^="bar-"]'); bars.forEach(bar => { - bar.style.backgroundColor = 'rgba(148, 163, 184, 0.5)'; + bar.style.backgroundColor = getBarColor(darkMode); bar.style.opacity = '1'; }); - }; - - // Auto-sort if switching to Binary Search to avoid confusion - useEffect(() => { - if (algorithm === 'BinarySearch') { - setArray(prev => [...prev].sort((a,b) => a-b)); - } - }, [algorithm]); + }, [arraySize, darkMode]); const handlePlay = () => { setIsPlaying(!isPlaying); }; @@ -449,16 +529,62 @@ const DsaVisualization = () => { if (arr.length > 0) { setArray(arr); setArraySize(arr.length); setIsPlaying(false); } }; - const algoOptions = { - sorting: ['BubbleSort', 'SelectionSort', 'InsertionSort', 'MergeSort', 'QuickSort'], - searching: ['BinarySearch', 'LinearSearch'], - graphs: ['BFS', 'DFS', 'Dijkstra', 'AStar'], - linkedlist: [], - trees: [], - heaps: [], - dp: [] + // Auto-sort for BinarySearch logic (if applicable for single algo viewing) + useEffect(() => { + if (activeTab === 'searching' && algorithm === 'BinarySearch') { + setArray(prev => [...prev].sort((a, b) => a - b)); + } + }, [algorithm, activeTab]); + + + useEffect(() => { + if (activeTab === 'sorting' || activeTab === 'searching') { + resetArray(); + } + }, [resetArray, activeTab]); + + // Cleanup finishedCount when playing starts or when the number of algorithms changes + useEffect(() => { + if (isPlaying) { + setFinishedCount(0); + } + }, [isPlaying, sortingAlgorithms.length]); + + // Check if all algorithms finished + useEffect(() => { + if (activeTab === 'sorting' && isPlaying && finishedCount >= sortingAlgorithms.length && sortingAlgorithms.length > 0) { + setIsPlaying(false); + } + }, [finishedCount, sortingAlgorithms.length, isPlaying, activeTab]); + + const handleAlgorithmFinished = () => { + setFinishedCount(prev => prev + 1); + }; + + const addAlgorithm = () => { + if (sortingAlgorithms.length < 6) { + setSortingAlgorithms([...sortingAlgorithms, 'BubbleSort']); + } + }; + + const removeAlgorithm = (index) => { + if (isPlaying) return; + if (sortingAlgorithms.length > 1) { + const newAlgos = [...sortingAlgorithms]; + newAlgos.splice(index, 1); + setSortingAlgorithms(newAlgos); + setFinishedCount(0); + } + }; + + const updateAlgorithm = (index, value) => { + const newAlgos = [...sortingAlgorithms]; + newAlgos[index] = value; + setSortingAlgorithms(newAlgos); }; + + return (
@@ -499,8 +625,8 @@ const DsaVisualization = () => {

- )} - > - {algo.replace(/([A-Z])/g, ' $1').trim()} - + ))} - - - {activeTab === 'sorting' && ( -
- - + {sortingAlgorithms.length < 6 && ( + + )}
- )} - {isComparisonMode && activeTab === 'sorting' && ( - + + + {algoOptions[activeTab]?.map(algo => ( - { ))} - )} - - )} + + ) + } {(activeTab === 'sorting' || activeTab === 'searching') && ( -
+
-
Size{arraySize}
- setArraySize(val[0])} disabled={isPlaying}/> +
Size{arraySize}
+ setArraySize(val[0])} disabled={isPlaying} />
-
Speed{speed}%
+
Speed{speed}%
setSpeed(val[0])} />
@@ -603,24 +741,23 @@ const DsaVisualization = () => { {(activeTab === 'sorting' || activeTab === 'searching') && (
)} - - {/* Fix: Added Search Target Input */} + {activeTab === 'searching' && (
- setSearchTarget(parseInt(e.target.value) || 0)} + setSearchTarget(parseInt(e.target.value) || 0)} className="h-9 text-sm" />
@@ -640,78 +777,101 @@ const DsaVisualization = () => {
- {activeTab === 'sorting' || activeTab === 'searching' ? ( -
- - -
-

{algorithm.replace(/([A-Z])/g, ' $1').trim()}

- {activeTab === 'searching' &&
Target: {searchTarget}
} -
- -
- 공급
- {isComparisonMode && ( + { + activeTab === 'sorting' ? ( +
+ {sortingAlgorithms.map((algo, index) => ( + + +
+

+ {algo.replace(/([A-Z])/g, ' $1').trim()} +

+
+ +
+
+ ))} +
+ ) : activeTab === 'searching' ? ( + // Searching View + // Use 'algorithm' state instead of 'sortingAlgorithms[0]' +
-
-

{secondAlgorithm.replace(/([A-Z])/g, ' $1').trim()}

+
+

{algorithm.replace(/([A-Z])/g, ' $1').trim()}

+
Target: {searchTarget}
- + - )} -
- ) : activeTab === 'graphs' ? ( - - -
-

Graph Algorithms

-
- setIsPlaying(false)} darkMode={darkMode} /> -
-
- ) : activeTab === 'linkedlist' ? ( - - -
-

Linked List Visualizer

-
- -
-
- ) : activeTab === 'trees' ? ( - - -
-

Binary Search Tree

-
- -
-
- ) : activeTab === 'heaps' ? ( - - -
-

Heap Visualizer (Max)

-
- -
-
- ) : activeTab === 'dp' ? ( - - -
-

Dynamic Programming

-
- -
-
- ) : ( - -

Under Construction

-
- )} +
+ ) : activeTab === 'graphs' ? ( + + +
+

Graph Algorithms

+
+ setIsPlaying(false)} darkMode={darkMode} /> +
+
+ ) : activeTab === 'linkedlist' ? ( + + +
+

Linked List Visualizer

+
+ +
+
+ ) : activeTab === 'trees' ? ( + + +
+

Binary Search Tree

+
+ +
+
+ ) : activeTab === 'heaps' ? ( + + +
+

Heap Visualizer (Max)

+
+ +
+
+ ) : activeTab === 'dp' ? ( + + +
+

Dynamic Programming

+
+ +
+
+ ) : ( + +

Under Construction

+
+ ) + }