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

117 lines
5.0 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.
"""검증 B v4: dx1.png 중심 + 주변 텍스트 배치.
dx1.png가 DX/GIS/BIM/디지털트윈 전체 관계를 보여주는 중심 이미지.
이미지 주변에 원본 텍스트로 관계를 설명.
"""
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))
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_core_v4_{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 = """다음 콘텐츠를 본심 영역 HTML로 만들어라. 707px × 293px.
## 핵심: dx1.png 이미지가 중심
이 이미지는 Digital Transformation, GIS, BIM, Metaverse(Digital Twin)의 관계를 보여주는 다이어그램이다.
이 이미지 하나가 전체 관계를 시각적으로 보여주므로, 이미지를 중심에 크게 배치하고 주변에 텍스트로 보충한다.
## 구조
1. 이미지를 중앙 또는 좌측에 크게 배치:
<img src="D:/ad-hoc/cel/public/assets/images/dx1.png" style="max-width:320px; border-radius:8px; border:1px solid #e2e8f0;">
2. 이미지 오른쪽 또는 아래에 텍스트 배치 (원본 그대로 사용):
"DX는 BIM, GIS, 디지털 트윈 등 핵심기술의 융합을 통해서만 실현 가능한 상위개념이다."
• GIS: 지리적 데이터를 공간 분석하여 시각적으로 표현, 위치기반 정보 제공
• BIM: 시설물의 생애주기 동안 발생한 모든 정보를 3차원 모델 기반으로 통합·관리하는 정보 관리 도구
• 디지털 트윈: 현실 세계의 물리적 객체나 시스템을 디지털 환경에 동일하게 구현하는 기술
3. 오른쪽 상단에 팝업:
<details><summary style="font-size:11px; color:#2563eb; cursor:pointer; font-weight:bold;">📊 DX vs BIM 상세 비교표</summary>
표:
| 기준 | DX | BIM |
| 범위 | BIM << DX (Engineering + Management 통합) | Only 3D (형상 구현 중심) |
| 프로세스 | 근본적 문제의식을 통한 개선 | 기존 2D 설계 방식 유지 |
| 활용 | 설계/시공 생산성 혁신 | 3D 모델에 의한 일반적 이해 향상 |
| 확장성 | 전 생애주기 활용 시스템 | (설계/시공/운영) 분야별 단절 |
| 주체 | 자체 수행 능력 — 지속가능성 확보 | S/W 제작사 판매 정책에 의존 |
</details>
4. 하단에 핵심 메시지:
background: #f0f9ff, border: 2px solid #bae6fd, border-radius: 8px, padding: 8px
"BIM ≠ DX — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다"
"BIM ≠ DX": color: #dc2626, font-weight: 900
## 디자인
- 이미지+텍스트를 flex로 가로 배치 (이미지 왼쪽, 텍스트 오른쪽)
- 텍스트: 11px #475569, line-height: 1.6
- 각 기술명(GIS, BIM, 디지털 트윈): bold #1e293b
- 전체 293px 안에 맞출 것
- "상위개념", "하위기술" 같은 단어 사용 금지
HTML + inline <style>만 반환. 설명 없이 코드만."""
print("=== 검증 B v4: dx1.png 중심 ===")
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 / "B_core_v4.html").write_text(wrapped, encoding="utf-8")
s = await asyncio.to_thread(capture_slide_screenshot, wrapped)
if s:
(out_dir / "B_core_v4.png").write_bytes(base64.b64decode(s))
print(f" [{time.time()-t0:.0f}s] 완료")
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())