Files
C.E.L_Slide_test2/scripts/verify_venn.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

109 lines
4.4 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개 기술이 서로 겹쳐서 융합을 표현하고, DX가 전체를 감싸는 구조.
"""
from __future__ import annotations
import asyncio, json, sys, time, datetime, base64, re
from pathlib import Path
ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(ROOT))
async def main():
from src.slide_measurer import capture_slide_screenshot
from src.config import settings
import anthropic
out_dir = ROOT / "data" / "runs" / f"verify_venn_{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()
prompt = """다음 포함 관계를 SVG 벤 다이어그램으로 시각화하는 HTML을 만들어라.
## 관계 구조
- DX(디지털 전환)는 상위개념이다 — 전체를 감싸는 가장 큰 원 또는 박스.
- DX 안에 GIS, BIM, 디지털 트윈 3개 기술이 있다.
- 이 3개 기술은 **서로 겹쳐서 융합**된다 — 벤 다이어그램처럼 원이 겹치는 부분이 있어야 한다.
- 3개가 겹치는 중심 영역 = "기술 융합" 또는 "DX 실현"
## 시각화 요구사항 (SVG 사용)
1. 전체 크기: 707px × 250px
2. DX 큰 원 또는 둥근 박스가 전체를 감싼다:
- fill: rgba(37,99,235,0.08), stroke: #2563eb, stroke-width: 2
- 상단 라벨: "DX (상위개념)"
3. 내부에 3개 원이 서로 겹쳐서 배치:
- GIS 원: cx=250, cy=120, r=80, fill: rgba(59,130,246,0.2), stroke: #3b82f6
- BIM 원: cx=350, cy=120, r=80, fill: rgba(16,185,129,0.2), stroke: #10b981
- 디지털트윈 원: cx=450, cy=120, r=80, fill: rgba(245,158,11,0.2), stroke: #f59e0b
- 각 원이 약 30-40px씩 겹쳐야 한다 (완전 분리 아님)
4. 각 원 안에 텍스트:
- 이름 (14px bold)
- 한 줄 설명 (10px)
5. 3개가 겹치는 중심 영역에 "융합" 또는 "DX 실현" 텍스트 (작게)
6. 아래에 핵심 메시지: "BIM ≠ DX — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다"
- background: #f0f9ff, border: 2px solid #bae6fd, border-radius: 8px
- "BIM ≠ DX" 부분: color: #dc2626, font-weight: 900
## 텍스트 (원본 그대로)
- GIS: "지리적 데이터를 공간 분석하여 시각적으로 표현"
- BIM: "시설물 생애주기 정보를 3차원 모델로 통합·관리"
- 디지털 트윈: "현실 객체를 디지털로 동일하게 구현"
HTML + inline <style> + <svg>를 포함하여 반환. 설명 없이 코드만."""
print("=== 벤 다이어그램 검증 (Claude Sonnet) ===")
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 / "venn.html").write_text(wrapped, encoding="utf-8")
s = await asyncio.to_thread(capture_slide_screenshot, wrapped)
if s:
(out_dir / "venn.png").write_bytes(base64.b64decode(s))
print(f" [{time.time()-t0:.0f}s] 완료. HTML {len(html)}")
print(f" 결과: {out_dir}")
except Exception as e:
print(f" 오류: {e}")
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())