Skip to content

Commit e29bac0

Browse files
committed
알고리즘 감지 시스템 개선
1 parent a4d5163 commit e29bac0

1 file changed

Lines changed: 53 additions & 49 deletions

File tree

src/components/ide/VisualizationModal.jsx

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// VisualizationModal.jsx - 확대/축소 상태 유지 버전
1+
// VisualizationModal.jsx - AnimationFactory 감지 로직 활용 버전
22
import React, { useState, useEffect, useCallback, useRef } from 'react';
33
import ReactDOM from 'react-dom';
44
import AnimationFactory from './AnimationFactory';
@@ -104,15 +104,14 @@ const ControlButton = ({ onClick, disabled, variant = 'default', children, title
104104
);
105105
};
106106

107-
// 🎮 시각화 컨트롤 (확대/축소 제거)
107+
// 🎮 시각화 컨트롤
108108
const VisualizationControls = ({
109109
isPlaying, currentStep, totalSteps, speed,
110110
onPlay, onPause, onStepBack, onStepForward, onReset, onSpeedChange, onStepChange,
111111
theme
112112
}) => {
113113
return (
114114
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', flexWrap: 'wrap' }}>
115-
{/* 재생 컨트롤 */}
116115
<ControlButton
117116
onClick={isPlaying ? onPause : onPlay}
118117
disabled={totalSteps === 0}
@@ -135,7 +134,6 @@ const VisualizationControls = ({
135134
⏮ 처음
136135
</ControlButton>
137136

138-
{/* 단계 표시 */}
139137
<div style={{
140138
display: 'flex',
141139
alignItems: 'center',
@@ -173,7 +171,6 @@ const VisualizationControls = ({
173171
<span style={{ fontSize: '12px', color: theme.colors.textLight }}>/ {totalSteps}</span>
174172
</div>
175173

176-
{/* 속도 컨트롤 */}
177174
<div style={{
178175
display: 'flex',
179176
alignItems: 'center',
@@ -212,7 +209,7 @@ const VisualizationControls = ({
212209
};
213210

214211
// 📊 정보 패널
215-
const InfoPanel = ({ data, currentStep, totalSteps, theme }) => {
212+
const InfoPanel = ({ data, currentStep, totalSteps, animationType, theme }) => {
216213
const InfoCard = ({ title, icon, children }) => (
217214
<div style={{
218215
background: theme.colors.card,
@@ -244,6 +241,24 @@ const InfoPanel = ({ data, currentStep, totalSteps, theme }) => {
244241
];
245242
const hasComplexityData = complexityItems.some(item => item.value && item.value !== '-');
246243

244+
// 🎯 감지된 알고리즘 타입 표시
245+
const getAlgorithmLabel = (type) => {
246+
const labels = {
247+
'bubble-sort': '버블 정렬',
248+
'selection-sort': '선택 정렬',
249+
'insertion-sort': '삽입 정렬',
250+
'merge-sort': '병합 정렬',
251+
'quick-sort': '퀵 정렬',
252+
'binary-tree': '이진 트리',
253+
'heap': '힙',
254+
'graph': '그래프',
255+
'linked-list': '연결 리스트',
256+
'recursion': '재귀',
257+
'variables': '변수'
258+
};
259+
return labels[type] || type;
260+
};
261+
247262
return (
248263
<div style={{
249264
display: 'flex',
@@ -280,6 +295,7 @@ const InfoPanel = ({ data, currentStep, totalSteps, theme }) => {
280295
<InfoCard title="시각화 정보" icon="📊">
281296
<div style={{ display: 'flex', flexDirection: 'column', gap: '6px' }}>
282297
{[
298+
{ label: '알고리즘', value: getAlgorithmLabel(animationType) },
283299
{ label: '이벤트 수', value: `${data?.events?.length || 0}개` },
284300
{ label: '현재 이벤트', value: currentEvent?.kind || '-' }
285301
].map((item, index) => (
@@ -400,43 +416,6 @@ const AnimationDisplay = ({ data, currentStep, totalSteps, animationType, isPlay
400416
);
401417
};
402418

403-
// 알고리즘 감지 (기존 로직 유지)
404-
const detectAlgorithmFromEvents = (events) => {
405-
if (!events || events.length === 0) return 'variables';
406-
407-
for (let i = 0; i < events.length; i++) {
408-
const event = events[i];
409-
if (event.viz?.type) {
410-
const vizType = event.viz.type.toLowerCase();
411-
if (vizType === 'heap') return 'heap';
412-
if (vizType === 'bst' || vizType === 'tree') return 'binary-tree';
413-
if (vizType === 'graph') return 'graph';
414-
if (vizType === 'list' || vizType === 'linkedlist') return 'linked-list';
415-
}
416-
}
417-
418-
const heapEvent = events.find(e => e.kind === 'ds_op' && e.target?.toLowerCase().includes('heap'));
419-
if (heapEvent) return 'heap';
420-
421-
const listEvent = events.find(e => e.kind === 'ds_op' && e.target && (e.target.toLowerCase().includes('list') || e.target.toLowerCase().includes('linkedlist') || e.target.toLowerCase().includes('node')));
422-
if (listEvent) return 'linked-list';
423-
424-
const graphEvent = events.find(e => e.kind === 'ds_op' && e.target && (e.target.toLowerCase().includes('graph') || e.target.toLowerCase().includes('adj')));
425-
if (graphEvent) return 'graph';
426-
427-
const treeEvent = events.find(e => e.kind === 'ds_op' && e.target && (e.target.toLowerCase().includes('tree') || e.target.toLowerCase().includes('bst')));
428-
if (treeEvent) return 'binary-tree';
429-
430-
const recursionEvents = events.filter(e => e.kind === 'call' && e.viz?.recursionDepth !== undefined);
431-
if (recursionEvents.length > 0) return 'recursion';
432-
433-
const hasCompare = events.some(e => e.kind === 'compare');
434-
const hasSwap = events.some(e => e.kind === 'swap');
435-
if (hasCompare && hasSwap) return 'bubble-sort';
436-
437-
return 'variables';
438-
};
439-
440419
// 📦 메인 모달
441420
const VisualizationModal = ({
442421
isOpen,
@@ -457,6 +436,24 @@ const VisualizationModal = ({
457436
const theme = getTheme(isDark);
458437
const animationControls = useAnimationControls(totalSteps);
459438

439+
// ✅ AnimationFactory의 감지 로직 활용 (한 번만 실행)
440+
const detectAndSetAnimationType = useCallback((events) => {
441+
if (!events || events.length === 0) {
442+
console.log('⚠️ 이벤트가 없어 기본값 사용');
443+
return 'variables';
444+
}
445+
446+
try {
447+
// 🎯 AnimationFactory의 고급 감지 로직 사용
448+
const detectedType = AnimationFactory.detectAnimationType(events);
449+
console.log('✅ AnimationFactory 감지 결과:', detectedType);
450+
return detectedType;
451+
} catch (error) {
452+
console.error('❌ 알고리즘 감지 실패:', error);
453+
return 'variables';
454+
}
455+
}, []);
456+
460457
// 데이터 가져오기
461458
const fetchVisualizationData = async () => {
462459
if (!code?.trim() && !preloadedJsonData) {
@@ -474,7 +471,7 @@ const VisualizationModal = ({
474471
const steps = preloadedJsonData.events?.length || 0;
475472
setTotalSteps(steps);
476473
animationControls.reset();
477-
const detectedType = detectAlgorithmFromEvents(preloadedJsonData.events);
474+
const detectedType = detectAndSetAnimationType(preloadedJsonData.events);
478475
setAnimationType(detectedType);
479476
} catch (err) {
480477
setError(err.message);
@@ -495,7 +492,7 @@ const VisualizationModal = ({
495492
const steps = parsedJson.events?.length || 0;
496493
setTotalSteps(steps);
497494
animationControls.reset();
498-
const detectedType = detectAlgorithmFromEvents(parsedJson.events);
495+
const detectedType = detectAndSetAnimationType(parsedJson.events);
499496
setAnimationType(detectedType);
500497
} catch (err) {
501498
setError(`JSON 파싱 오류: ${err.message}`);
@@ -514,7 +511,7 @@ const VisualizationModal = ({
514511
const steps = visualizationData.events?.length || 0;
515512
setTotalSteps(steps);
516513
animationControls.reset();
517-
const detectedType = detectAlgorithmFromEvents(visualizationData.events);
514+
const detectedType = detectAndSetAnimationType(visualizationData.events);
518515
setAnimationType(detectedType);
519516
} catch (err) {
520517
setError(err.message);
@@ -529,7 +526,6 @@ const VisualizationModal = ({
529526
}
530527
}, [isOpen, preloadedJsonData]);
531528

532-
// 모달이 닫힐 때만 초기화
533529
useEffect(() => {
534530
if (!isOpen) {
535531
setData(null);
@@ -687,10 +683,18 @@ const VisualizationModal = ({
687683
minHeight: 0
688684
}}
689685
className="visualization-scrollbar">
690-
{data && <InfoPanel data={data} currentStep={animationControls.currentStep} totalSteps={totalSteps} theme={theme} />}
686+
{data && (
687+
<InfoPanel
688+
data={data}
689+
currentStep={animationControls.currentStep}
690+
totalSteps={totalSteps}
691+
animationType={animationType}
692+
theme={theme}
693+
/>
694+
)}
691695
</div>
692696

693-
{/* 오른쪽: 애니메이션만 */}
697+
{/* 오른쪽: 애니메이션 */}
694698
<div style={{
695699
background: theme.colors.card,
696700
overflowY: 'auto',

0 commit comments

Comments
 (0)