Files
C.E.L_Slide_test2/scripts/verify_hierarchy_3ways.py
kyeongmin 29f56187c0 Phase P~S 전체 작업물: 검증 스크립트, 블록 템플릿, 설계 문서, 코드 수정
포함 내용:
- Phase P/Q/R/S 설계 문서 (IMPROVEMENT-PHASE-*.md)
- 영역별 검증 스크립트 (scripts/verify_*.py, test_*.py)
- 블록 템플릿 추가 (cards, emphasis 변형)
- 코드 수정: block_search, content_editor, design_director, slide_measurer
- catalog.yaml 블록 목록 업데이트
- CLAUDE.md, PROGRESS.md, README.md 업데이트

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 08:38:06 +09:00

130 lines
4.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""DX 포함 관계를 3가지 다른 시각화로 비교.
A: 벤 다이어그램 (원 안에 이름만, 설명은 하단 별도)
B: 동심원 (DX 큰 원 > 기술융합 중간 원 > GIS/BIM/DT 작은 원)
C: 계층 박스 (DX 박스 안에 3개 기술 + 겹치는 영역 표시)
"""
from __future__ import annotations
import asyncio, sys, time, datetime, base64, re
from pathlib import Path
ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(ROOT))
COMMON_INFO = """
## 관계 (반드시 반영)
- DX는 상위개념. GIS, BIM, 디지털 트윈을 포함.
- 3개 기술은 서로 융합되어 DX를 실현.
- "BIM ≠ DX"
## 텍스트
- DX: 상위개념 (디지털 전환)
- GIS: 공간 정보
- BIM: 3차원 모델
- 디지털 트윈: 디지털 구현
- 핵심 메시지: "BIM ≠ DX — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다"
## 공통 규칙
- 크기: 707px × 280px
- 원 안에는 이름만 (설명 텍스트를 원 안에 넣지 마라)
- 각 기술의 설명은 원 아래에 작은 텍스트로 별도 배치하거나 생략
- "BIM ≠ DX" 강조 박스는 하단에 배치
- 색상: GIS=#3b82f6, BIM=#10b981, 디지털트윈=#f59e0b, DX=#2563eb
- 폰트: Pretendard Variable
HTML + inline <style> 반환. 설명 없이 코드만.
"""
async def main():
from src.slide_measurer import capture_slide_screenshot
from src.config import settings
import anthropic
out_dir = ROOT / "data" / "runs" / f"hierarchy_3ways_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}"
out_dir.mkdir(parents=True, exist_ok=True)
client = anthropic.AsyncAnthropic(api_key=settings.anthropic_api_key)
t0 = time.time()
prompts = {
"A_venn": f"""DX 포함 관계를 **벤 다이어그램**으로 시각화하라.
- SVG로 3개 원을 서로 30% 겹치게 배치
- 각 원 안에 이름과 아이콘 글자(G, B, T)만 표시 (설명 넣지 마라)
- DX 큰 둥근 박스가 3개 원을 감싼다
- 3개가 겹치는 중심에 "융합" 텍스트
- 원 아래에 각 기술명 + 한 줄 설명을 가로로 나열
{COMMON_INFO}""",
"B_concentric": f"""DX 포함 관계를 **동심원 구조**로 시각화하라.
- 가장 큰 원: DX (연한 파란 배경)
- 중간 원: "기술 융합" (약간 진한 파란)
- 안쪽에 GIS, BIM, 디지털트윈 3개 작은 원이 삼각형으로 배치
- 각 원 안에 이름만 (G, B, T 아이콘 + 이름)
- 아래에 각 기술 한 줄 설명
{COMMON_INFO}""",
"C_nested_boxes": f"""DX 포함 관계를 **중첩 박스**로 시각화하라.
- DX 큰 박스 (border: 3px solid #2563eb, 둥근 모서리)
- 안에 3개 기술 카드가 가로로 배치
- 카드 사이에 겹치는 영역을 그라데이션 또는 점선으로 표시 (융합을 시각적으로)
- 각 카드: 원형 아이콘(G/B/T) + 이름 + 한 줄 설명
- DX 박스 상단에 라벨: "DX — 디지털 전환 (상위개념)"
- 카드들 아래에 "3개 기술이 융합되어 DX를 실현" 텍스트
{COMMON_INFO}""",
}
for name, prompt in prompts.items():
print(f"\n=== {name} ===")
try:
response = await client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=8192,
messages=[{"role": "user", "content": prompt}],
)
text = response.content[0].text if response.content else ""
match = re.search(r"```html\s*(.*?)```", text, re.DOTALL)
html = match.group(1).strip() if match else text.strip()
wrapped = f"""<!DOCTYPE html>
<html lang="ko"><head><meta charset="UTF-8">
<style>
@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css');
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
.slide {{
width: 1280px; height: 720px; overflow: hidden; background: white;
font-family: 'Pretendard Variable', sans-serif;
display: flex; align-items: center; justify-content: center;
}}
.test-container {{ width: 707px; }}
</style>
</head><body>
<div class="slide"><div class="test-container">
{html}
</div></div>
</body></html>"""
(out_dir / f"{name}.html").write_text(wrapped, encoding="utf-8")
s = await asyncio.to_thread(capture_slide_screenshot, wrapped)
if s:
(out_dir / f"{name}.png").write_bytes(base64.b64decode(s))
print(f" [{time.time()-t0:.0f}s] 완료")
except Exception as e:
print(f" 오류: {e}")
print(f"\n총 소요: {time.time()-t0:.0f}")
print(f"결과: {out_dir}")
if __name__ == "__main__":
import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", datefmt="%H:%M:%S")
logging.getLogger("selenium").setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.getLogger("httpx").setLevel(logging.WARNING)
asyncio.run(main())