diff --git a/.gitignore b/.gitignore index e4312f3..b701b4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ venv/ build/ -dist/ \ No newline at end of file +dist/ +__pycache__ \ No newline at end of file diff --git a/app/data/fast_parser.py b/app/data/fast_parser.py index 5ec27d4..5c3c82f 100644 --- a/app/data/fast_parser.py +++ b/app/data/fast_parser.py @@ -2,6 +2,10 @@ import os import numpy as np import os import numpy as np +import os +import numpy as np +import os +import numpy as np import polars as pl from typing import Optional @@ -9,10 +13,9 @@ class FastLogParser: CHUNK_SIZE = 84 @staticmethod - def parse_to_parquet(input_path: str, output_path: str = None) -> Optional[str]: + def parse(input_path: str) -> Optional[pl.DataFrame]: """ - Numpy 벡터 연산을 사용하여 MMI 바이너리 로그를 초고속으로 파싱 후 Parquet 저장. - (VDI/VDO 포함 모든 필드 완벽 구현) + Numpy 벡터 연산을 사용하여 MMI 바이너리 로그를 초고속으로 파싱 후 DataFrame 반환. """ if not os.path.exists(input_path): return None @@ -241,6 +244,24 @@ class FastLogParser: # [Optional] 여기서 역 이름 매핑이나 코드 변환을 수행할 수 있음 # (이전 대화의 Processor 로직을 여기에 통합해도 됨) + return df + + except Exception as e: + print(f"[FastParser] Error: {e}") + import traceback + traceback.print_exc() + return None + + @staticmethod + def parse_to_parquet(input_path: str, output_path: str = None) -> Optional[str]: + """ + MMI 바이너리 로그를 파싱하여 Parquet로 저장 (Wrapper) + """ + df = FastLogParser.parse(input_path) + if df is None: + return None + + try: if output_path is None: output_path = input_path.replace(".dat", ".parquet") diff --git a/app/ui/__pycache__/analysis_panel.cpython-311.pyc b/app/ui/__pycache__/analysis_panel.cpython-311.pyc index 6ac9fdf..bd632fb 100644 Binary files a/app/ui/__pycache__/analysis_panel.cpython-311.pyc and b/app/ui/__pycache__/analysis_panel.cpython-311.pyc differ diff --git a/app/ui/__pycache__/main_window.cpython-311.pyc b/app/ui/__pycache__/main_window.cpython-311.pyc index 4011a04..8715d2b 100644 Binary files a/app/ui/__pycache__/main_window.cpython-311.pyc and b/app/ui/__pycache__/main_window.cpython-311.pyc differ diff --git a/app/ui/main_window.py b/app/ui/main_window.py index 968c4d0..88926a2 100644 --- a/app/ui/main_window.py +++ b/app/ui/main_window.py @@ -18,51 +18,74 @@ from app.core.settings import get_settings_manager from app.ui.widgets.ai_floating_chat import AIFloatingButton, AIChatDialog, animate_open, animate_close +from PySide6.QtCore import Qt, QRect, QTimer + class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("SL200 AI Smart Analyzer") self.resize(1800, 1000) - self.setup_ui() + # 1. 기본 UI 골격만 즉시 생성 (매우 빠름) + self.setup_ui_skeleton() self.setup_menubar() self.setup_toolbar() - # 패널 데이터 로드 시 날짜 비교를 위한 시그널 연결 - self.left_panel.data_loaded.connect(self.check_sync_availability) - self.right_panel.data_loaded.connect(self.check_sync_availability) + # 2. 무거운 컴포넌트(패널, AI)는 윈도우가 뜬 직후 지연 로딩 + # 0ms: 이벤트 루프가 돌기 시작한 직후 실행 (윈도우 표시 후) + QTimer.singleShot(10, self._init_panels) + + # 500ms: 패널 로딩 후 실행 + QTimer.singleShot(500, self._init_ai_client) - # AI 클라이언트 초기화 - self._init_ai_client() - - def setup_ui(self): + def setup_ui_skeleton(self): + """기본 UI 골격 생성 (빈 패널)""" central = QWidget() self.setCentralWidget(central) - layout = QVBoxLayout(central) + self.main_layout = QVBoxLayout(central) - # 좌우 분할 - splitter = QSplitter(Qt.Orientation.Horizontal) - - # 왼쪽/오른쪽 패널 생성 (ID 부여) - self.left_panel = AnalysisPanel("left") - self.right_panel = AnalysisPanel("right") - - splitter.addWidget(self.left_panel) - splitter.addWidget(self.right_panel) - splitter.setSizes([900, 900]) # 1:1 비율 - - layout.addWidget(splitter) + # 좌우 분할 (빈 상태로 생성) + self.splitter = QSplitter(Qt.Orientation.Horizontal) + self.main_layout.addWidget(self.splitter) self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) + self.status_bar.showMessage("초기화 중...") - # 플로팅 AI 버튼 + # 플로팅 AI 버튼 (미리 생성하되 기능은 나중에 연결) self._ai_button = AIFloatingButton(central) - self._ai_button.clicked.connect(self._open_ai_chat) self._ai_button.show() self._ai_chat: AIChatDialog | None = None self._ai_button.move_to_bottom_right() + def _init_panels(self): + """패널 지연 생성""" + try: + # 왼쪽/오른쪽 패널 생성 (ID 부여) + # 여기가 가장 시간이 많이 걸리는 부분 (약 0.5~1초) + self.left_panel = AnalysisPanel("left") + self.right_panel = AnalysisPanel("right") + + self.splitter.addWidget(self.left_panel) + self.splitter.addWidget(self.right_panel) + self.splitter.setSizes([900, 900]) # 1:1 비율 + + # 패널 데이터 로드 시 날짜 비교를 위한 시그널 연결 + self.left_panel.data_loaded.connect(self.check_sync_availability) + self.right_panel.data_loaded.connect(self.check_sync_availability) + + # AI 버튼 클릭 연결 + self._ai_button.clicked.connect(self._open_ai_chat) + + self.status_bar.showMessage("준비 완료", 3000) + print("[MainWindow] Panels initialized lazily.") + + except Exception as e: + print(f"[MainWindow] Panel initialization failed: {e}") + self.status_bar.showMessage(f"초기화 오류: {e}") + + # setup_ui 메서드는 제거 (setup_ui_skeleton으로 대체됨) + def resizeEvent(self, event): super().resizeEvent(event) try: diff --git a/app/ui/views/__pycache__/dashboard_view.cpython-311.pyc b/app/ui/views/__pycache__/dashboard_view.cpython-311.pyc index 6dfa2d0..8daa93d 100644 Binary files a/app/ui/views/__pycache__/dashboard_view.cpython-311.pyc and b/app/ui/views/__pycache__/dashboard_view.cpython-311.pyc differ diff --git a/main.py b/main.py index 9e155e4..0822e38 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,7 @@ from PySide6.QtWidgets import QApplication from app.ui.main_window import MainWindow def main(): + # 시작 시간 측정 start_time = time.time() print(f"[STARTUP] Application starting at {time.strftime('%H:%M:%S')}") @@ -12,20 +13,19 @@ def main(): app = QApplication(sys.argv) print(f"[STARTUP] QApplication created in {time.time() - t0:.3f}s") - # 다크 테마나 스타일시트 적용 가능 + # 스타일 설정 print("[STARTUP] Setting style...") t0 = time.time() app.setStyle("Fusion") print(f"[STARTUP] Style set in {time.time() - t0:.3f}s") - # 역 정보는 파일 로드 시점에 자동으로 로드됨 (지연 로딩) - # TrackInfo.load_info() 호출 제거 - 불필요한 초기 로딩 방지 - + # 메인 윈도우 생성 (지연 로딩 적용됨) print("[STARTUP] Creating MainWindow...") t0 = time.time() window = MainWindow() print(f"[STARTUP] MainWindow created in {time.time() - t0:.3f}s") + # 윈도우 표시 print("[STARTUP] Showing window...") t0 = time.time() window.show()