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>
This commit is contained in:
1 parent
0e4b8c091c
commit
29f56187c0
44 files changed
+9431
-313
No files matched your search
@@ -0,0 +1,146 @@
|
||||
"""본심 이미지+텍스트 배치 3가지 비교.
|
||||
|
||||
dx1.png (612x224, 가로형) + 관계 텍스트를 293px 안에 배치.
|
||||
A: 상단 이미지 + 하단 텍스트
|
||||
B: 왼쪽 텍스트(55%) + 오른쪽 이미지(45%)
|
||||
C: 상단 이미지(중앙) + 좌우 텍스트
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import asyncio, sys, datetime, base64
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
IMG_PATH = "data:image/png;base64,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 truncated
|
||||
|
||||
# 공통 텍스트
|
||||
TEXTS = {
|
||||
"main": "DX는 BIM, GIS, 디지털 트윈 등 핵심기술의 융합을 통해서만 실현 가능한 상위개념이다.",
|
||||
"gis": "GIS: 지리적 데이터를 공간 분석하여 시각적으로 표현, 위치기반 정보 제공",
|
||||
"bim": "BIM: 시설물의 생애주기 동안 발생한 모든 정보를 3차원 모델 기반으로 통합·관리하는 정보 관리 도구",
|
||||
"dt": "디지털 트윈: 현실 세계의 물리적 객체나 시스템을 디지털 환경에 동일하게 구현하는 기술",
|
||||
"conclusion": "DX는 이들 기술을 통합하여 업무방식과 가치 창출 구조를 근본적으로 전환하는 과정 및 결과이다.",
|
||||
"key": "BIM ≠ DX — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다",
|
||||
}
|
||||
|
||||
CSS_COMMON = """
|
||||
<style>
|
||||
* { margin:0; padding:0; box-sizing:border-box; }
|
||||
.core { width:707px; height:293px; font-family:'Pretendard Variable',sans-serif; font-size:11px; color:#1e293b; line-height:1.6; overflow:hidden; display:flex; flex-direction:column; }
|
||||
.core img { border-radius:6px; border:1px solid #e2e8f0; object-fit:contain; }
|
||||
.core .main-text { font-size:12px; font-weight:500; color:#1e293b; margin-bottom:6px; }
|
||||
.core .bullet { font-size:11px; color:#475569; margin-bottom:3px; padding-left:12px; position:relative; }
|
||||
.core .bullet::before { content:'•'; position:absolute; left:0; color:#2563eb; }
|
||||
.core .bullet b { color:#1e293b; }
|
||||
.core .key-msg { background:#f0f9ff; border:2px solid #bae6fd; border-radius:6px; padding:6px 12px; text-align:center; font-size:12px; font-weight:700; color:#0c4a6e; margin-top:auto; }
|
||||
.core .key-msg em { color:#dc2626; font-style:normal; font-weight:900; }
|
||||
.core .details-link { font-size:10px; color:#2563eb; cursor:pointer; font-weight:700; text-align:right; }
|
||||
</style>
|
||||
"""
|
||||
|
||||
|
||||
def layout_A():
|
||||
"""상단 이미지(가운데, 너비 400px) + 하단 텍스트"""
|
||||
return f"""{CSS_COMMON}
|
||||
<div class="core">
|
||||
<div style="text-align:center; margin-bottom:8px;">
|
||||
<img src="{IMG_PATH}" style="width:400px; height:auto;">
|
||||
</div>
|
||||
<div class="main-text">{TEXTS['main']}</div>
|
||||
<div class="bullet"><b>GIS</b>: 지리적 데이터를 공간 분석하여 시각적으로 표현, 위치기반 정보 제공</div>
|
||||
<div class="bullet"><b>BIM</b>: 시설물의 생애주기 동안 발생한 모든 정보를 3차원 모델 기반으로 통합·관리하는 정보 관리 도구</div>
|
||||
<div class="bullet"><b>디지털 트윈</b>: 현실 세계의 물리적 객체나 시스템을 디지털 환경에 동일하게 구현하는 기술</div>
|
||||
<div class="key-msg"><em>BIM ≠ DX</em> — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다</div>
|
||||
</div>"""
|
||||
|
||||
|
||||
def layout_B():
|
||||
"""왼쪽 텍스트(55%) + 오른쪽 이미지(45%)"""
|
||||
return f"""{CSS_COMMON}
|
||||
<div class="core">
|
||||
<div style="display:flex; gap:16px; flex:1;">
|
||||
<div style="flex:55%; display:flex; flex-direction:column;">
|
||||
<div class="main-text">{TEXTS['main']}</div>
|
||||
<div class="bullet"><b>GIS</b>: 지리적 데이터를 공간 분석하여 시각적으로 표현, 위치기반 정보 제공</div>
|
||||
<div class="bullet"><b>BIM</b>: 시설물의 생애주기 동안 발생한 모든 정보를 3차원 모델 기반으로 통합·관리하는 정보 관리 도구</div>
|
||||
<div class="bullet"><b>디지털 트윈</b>: 현실 세계의 물리적 객체나 시스템을 디지털 환경에 동일하게 구현하는 기술</div>
|
||||
<div style="margin-top:8px; font-size:11px; color:#1e293b; font-weight:500;">{TEXTS['conclusion']}</div>
|
||||
</div>
|
||||
<div style="flex:45%; display:flex; align-items:center;">
|
||||
<img src="{IMG_PATH}" style="width:100%; height:auto;">
|
||||
</div>
|
||||
</div>
|
||||
<div class="key-msg"><em>BIM ≠ DX</em> — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다</div>
|
||||
</div>"""
|
||||
|
||||
|
||||
def layout_C():
|
||||
"""이미지 상단 + 좌우 텍스트 분할 (DX 설명 | BIM 설명)"""
|
||||
return f"""{CSS_COMMON}
|
||||
<div class="core">
|
||||
<div style="text-align:center; margin-bottom:6px;">
|
||||
<img src="{IMG_PATH}" style="width:380px; height:auto;">
|
||||
</div>
|
||||
<div style="display:flex; gap:12px; flex:1;">
|
||||
<div style="flex:1; border-left:3px solid #2563eb; padding-left:10px;">
|
||||
<div style="font-size:12px; font-weight:700; color:#2563eb; margin-bottom:4px;">DX (Digital Transformation)</div>
|
||||
<div class="bullet">BIM, GIS, 디지털 트윈 등 핵심기술의 융합을 통해서만 실현 가능</div>
|
||||
<div class="bullet">업무방식과 가치 창출 구조를 근본적으로 전환하는 과정 및 결과</div>
|
||||
<div class="bullet">Engineering + Management 통합</div>
|
||||
</div>
|
||||
<div style="flex:1; border-left:3px solid #10b981; padding-left:10px;">
|
||||
<div style="font-size:12px; font-weight:700; color:#10b981; margin-bottom:4px;">BIM (Building Information Modeling)</div>
|
||||
<div class="bullet">시설물 생애주기 정보를 3차원 모델로 통합·관리하는 도구</div>
|
||||
<div class="bullet">건설 정보 기반의 Process와 Product를 제공</div>
|
||||
<div class="bullet">DX를 실현하기 위한 핵심 기술 중 하나</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="key-msg"><em>BIM ≠ DX</em> — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다</div>
|
||||
</div>"""
|
||||
|
||||
|
||||
def _wrap(inner):
|
||||
return 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;
|
||||
}}
|
||||
</style>
|
||||
</head><body>
|
||||
<div class="slide">
|
||||
{inner}
|
||||
</div>
|
||||
</body></html>"""
|
||||
|
||||
|
||||
async def main():
|
||||
from src.slide_measurer import capture_slide_screenshot
|
||||
|
||||
out_dir = ROOT / "data" / "runs" / f"layout_3_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
layouts = {"A_top_image": layout_A(), "B_left_text": layout_B(), "C_image_split": layout_C()}
|
||||
|
||||
for name, html in layouts.items():
|
||||
wrapped = _wrap(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" {name} 완료")
|
||||
|
||||
print(f"\n결과: {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)
|
||||
asyncio.run(main())
|
||||
Reference in new issue
Block a user