Generate separate slide outputs for three DX MDX inputs
This commit is contained in:
@@ -378,6 +378,65 @@ def _details_blocks(raw: str) -> list[str]:
|
||||
return re.findall(r'<details>(.*?)</details>', raw, flags=re.S)
|
||||
|
||||
|
||||
def _popup_list_html(items: list[str], floor: int = 90, ceiling: int = 260) -> str:
|
||||
if not items:
|
||||
return '<div style="font-size:12px; color:#64748b;">??? ?? ??? ????.</div>'
|
||||
lis = ''.join(
|
||||
f'<li style="margin-left:18px; margin-bottom:8px; line-height:1.55;">{_trim_visible_copy(item, floor=floor, ceiling=ceiling)}</li>'
|
||||
for item in items
|
||||
)
|
||||
return f'<ul style="margin:0; padding-left:0; list-style:disc; font-size:13px; color:#334155;">{lis}</ul>'
|
||||
|
||||
|
||||
def _popup_comparison_table(rows: list[tuple[str, str, str]]) -> str:
|
||||
if not rows:
|
||||
return '<div style="font-size:12px; color:#64748b;">??? ???? ????.</div>'
|
||||
body = ''.join(
|
||||
'<tr>'
|
||||
f'<td style="padding:10px 12px; border-top:1px solid #e2e8f0; font-size:12px; line-height:1.5; color:#1e3a8a; vertical-align:top;">{_trim_visible_copy(dx, floor=160, ceiling=420)}</td>'
|
||||
f'<td style="padding:10px 8px; border-top:1px solid #e2e8f0; font-size:12px; line-height:1.35; color:#1d4ed8; font-weight:800; background:#eff6ff; text-align:center; vertical-align:top;">{axis}</td>'
|
||||
f'<td style="padding:10px 12px; border-top:1px solid #e2e8f0; font-size:12px; line-height:1.5; color:#475569; vertical-align:top;">{_trim_visible_copy(bim, floor=160, ceiling=420)}</td>'
|
||||
'</tr>'
|
||||
for axis, dx, bim in rows
|
||||
)
|
||||
return (
|
||||
'<div style="border:1px solid #cfe0ff; border-radius:12px; overflow:hidden;">'
|
||||
'<table style="width:100%; border-collapse:collapse; table-layout:fixed;">'
|
||||
'<thead><tr style="background:linear-gradient(135deg,#0d47a1,#1565c0); color:#fff;">'
|
||||
'<th style="padding:10px 12px; font-size:13px;">DX</th>'
|
||||
'<th style="padding:10px 8px; font-size:13px; width:92px;">??</th>'
|
||||
'<th style="padding:10px 12px; font-size:13px;">BIM</th>'
|
||||
'</tr></thead>'
|
||||
f'<tbody>{body}</tbody></table></div>'
|
||||
)
|
||||
|
||||
|
||||
def _popup_button(button_id: str, label: str) -> str:
|
||||
return (
|
||||
f"<button type=\"button\" onclick=\"document.getElementById('{button_id}').style.display='flex'\" "
|
||||
'style="margin-top:6px; border:none; background:#eff6ff; color:#1d4ed8; border:1px solid #bfdbfe; '
|
||||
'border-radius:999px; padding:4px 10px; font-size:10px; font-weight:700; cursor:pointer;">'
|
||||
f'{label}</button>'
|
||||
)
|
||||
|
||||
|
||||
def _popup_overlay(popup_id: str, title: str, content_html: str) -> str:
|
||||
return (
|
||||
f'<div id="{popup_id}" style="display:none; position:fixed; inset:0; background:rgba(15,23,42,0.56); '
|
||||
'align-items:center; justify-content:center; z-index:9999; padding:28px;">'
|
||||
'<div style="width:min(920px, 92vw); max-height:88vh; overflow:auto; background:#ffffff; border-radius:18px; '
|
||||
'box-shadow:0 24px 80px rgba(15,23,42,0.28); padding:22px 24px 20px 24px;">'
|
||||
'<div style="display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:14px;">'
|
||||
f'<div style="font-size:20px; font-weight:900; color:#0f172a;">{title}</div>'
|
||||
f"<button type=\"button\" onclick=\"document.getElementById('{popup_id}').style.display='none'\" "
|
||||
'style="border:none; background:#e2e8f0; color:#334155; width:34px; height:34px; border-radius:999px; '
|
||||
'font-size:18px; font-weight:800; cursor:pointer;">?</button>'
|
||||
'</div>'
|
||||
f'{content_html}'
|
||||
'</div></div>'
|
||||
)
|
||||
|
||||
|
||||
def _evidence_bullets_from_raw(raw: str) -> list[str]:
|
||||
blocks = _details_blocks(raw)
|
||||
if not blocks:
|
||||
@@ -497,19 +556,20 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
|
||||
evidence_topic = _topic(ctx, 4)
|
||||
comparison_topic = _topic(ctx, 5)
|
||||
|
||||
problem_title = problem_topic.title if problem_topic and problem_topic.title else 'Problem'
|
||||
definitions_title = definitions_topic.title if definitions_topic and definitions_topic.title else 'Definitions'
|
||||
relation_title = relation_topic.title if relation_topic and relation_topic.title else 'Relationship'
|
||||
evidence_title = evidence_topic.title if evidence_topic and evidence_topic.title else 'Evidence'
|
||||
comparison_title = comparison_topic.title if comparison_topic and comparison_topic.title else 'Comparison'
|
||||
problem_title = problem_topic.title if problem_topic and problem_topic.title else '??? ??'
|
||||
definitions_title = definitions_topic.title if definitions_topic and definitions_topic.title else '?? ??'
|
||||
relation_title = relation_topic.title if relation_topic and relation_topic.title else '??? ????'
|
||||
evidence_title = evidence_topic.title if evidence_topic and evidence_topic.title else '?? ?? ??'
|
||||
comparison_title = comparison_topic.title if comparison_topic and comparison_topic.title else 'DX? BIM? ??'
|
||||
|
||||
problem_bullets = _problem_bullets_from_raw(raw)[:2]
|
||||
evidence_bullets = _evidence_bullets_from_raw(raw)[:3]
|
||||
all_evidence_bullets = _evidence_bullets_from_raw(raw)
|
||||
evidence_bullets = all_evidence_bullets[:2]
|
||||
definition_sections = _definition_sections_from_raw(raw)[:3]
|
||||
relation_bullets = _relation_bullets_from_raw(raw)[:4]
|
||||
relation_bullets = _relation_bullets_from_raw(raw)[:5]
|
||||
comparison_rows = _parse_comparison_rows_from_raw(raw)
|
||||
|
||||
preferred_axes = ['범위', '프로세스', '성과품', '확장성']
|
||||
preferred_axes = ['??', '????', '???', '???']
|
||||
picked_rows = [row for row in comparison_rows if row[0] in preferred_axes]
|
||||
if len(picked_rows) < 4:
|
||||
seen = {row[0] for row in picked_rows}
|
||||
@@ -519,7 +579,7 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
|
||||
seen.add(row[0])
|
||||
if len(picked_rows) >= 4:
|
||||
break
|
||||
picked_rows = picked_rows[:3]
|
||||
picked_rows = picked_rows[:4]
|
||||
|
||||
image_src = _extract_image_src_from_raw(raw)
|
||||
if image_src and ctx.base_path:
|
||||
@@ -532,26 +592,26 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
|
||||
conclusion_text = _conclusion_from_raw(raw)
|
||||
|
||||
problem_items_html = ''.join(
|
||||
f'<li style="margin-left:14px; margin-bottom:4px;">{_trim_visible_copy(item, floor=100, ceiling=220)}</li>'
|
||||
f'<li style="margin-left:16px; margin-bottom:5px;">{_trim_visible_copy(item, floor=130, ceiling=280)}</li>'
|
||||
for item in problem_bullets
|
||||
)
|
||||
evidence_items_html = ''.join(
|
||||
f'<li style="margin-left:14px; margin-bottom:4px;">{_trim_visible_copy(item, floor=84, ceiling=180)}</li>'
|
||||
f'<li style="margin-left:16px; margin-bottom:5px;">{_trim_visible_copy(item, floor=140, ceiling=320)}</li>'
|
||||
for item in evidence_bullets
|
||||
)
|
||||
relation_items_html = ''.join(
|
||||
f'<li style="margin-left:16px; margin-bottom:5px;">{_trim_visible_copy(item, floor=92, ceiling=210)}</li>'
|
||||
f'<li style="margin-left:18px; margin-bottom:6px;">{_trim_visible_copy(item, floor=120, ceiling=260)}</li>'
|
||||
for item in relation_bullets
|
||||
)
|
||||
|
||||
definition_cards_html = ''
|
||||
for idx, section in enumerate(definition_sections, start=1):
|
||||
definition_cards_html += (
|
||||
'<div style="background:#ffffff; border:1px solid #d7e2f0; border-radius:14px; padding:12px; display:flex; gap:10px; align-items:flex-start; min-height:96px;">'
|
||||
'<div style="background:#ffffff; border:1px solid #d7e2f0; border-radius:14px; padding:12px; display:flex; gap:10px; align-items:flex-start; min-height:108px;">'
|
||||
f'<div style="width:34px; height:34px; border-radius:999px; background:#2563eb; color:#fff; font-size:15px; font-weight:800; display:flex; align-items:center; justify-content:center; flex-shrink:0;">{idx}</div>'
|
||||
'<div style="flex:1;">'
|
||||
f'<div style="font-size:13px; font-weight:800; color:#0f172a; margin-bottom:6px; line-height:1.35;">{section["title"]}</div>'
|
||||
f'<div style="font-size:9.5px; line-height:1.55; color:#334155; word-break:keep-all;">{_trim_visible_copy(section["body"], floor=150, ceiling=330)}</div>'
|
||||
f'<div style="font-size:10px; line-height:1.58; color:#334155; word-break:keep-all;">{_trim_visible_copy(section["body"], floor=220, ceiling=520)}</div>'
|
||||
'</div>'
|
||||
'</div>'
|
||||
)
|
||||
@@ -560,22 +620,34 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
|
||||
for axis, dx, bim in picked_rows:
|
||||
comparison_rows_html += (
|
||||
'<div style="display:grid; grid-template-columns:1fr 86px 1fr; border-top:1px solid #dbe5f2; align-items:stretch;">'
|
||||
f'<div style="padding:6px 9px; font-size:9.4px; line-height:1.35; color:#1e3a8a; font-weight:600; background:#ffffff;">{_trim_visible_copy(dx, floor=72, ceiling=145)}</div>'
|
||||
f'<div style="padding:6px 6px; font-size:9.4px; line-height:1.25; color:#1d4ed8; font-weight:800; text-align:center; background:#eff6ff; border-left:1px solid #dbe5f2; border-right:1px solid #dbe5f2; display:flex; align-items:center; justify-content:center;">{axis}</div>'
|
||||
f'<div style="padding:6px 9px; font-size:9.4px; line-height:1.35; color:#475569; text-align:right; background:#ffffff;">{_trim_visible_copy(bim, floor=72, ceiling=145)}</div>'
|
||||
f'<div style="padding:7px 10px; font-size:9.8px; line-height:1.42; color:#1e3a8a; font-weight:600; background:#ffffff;">{_trim_visible_copy(dx, floor=110, ceiling=220)}</div>'
|
||||
f'<div style="padding:7px 6px; font-size:9.6px; line-height:1.25; color:#1d4ed8; font-weight:800; text-align:center; background:#eff6ff; border-left:1px solid #dbe5f2; border-right:1px solid #dbe5f2; display:flex; align-items:center; justify-content:center;">{axis}</div>'
|
||||
f'<div style="padding:7px 10px; font-size:9.8px; line-height:1.42; color:#475569; text-align:right; background:#ffffff;">{_trim_visible_copy(bim, floor=110, ceiling=220)}</div>'
|
||||
'</div>'
|
||||
)
|
||||
|
||||
evidence_popup_html = _popup_overlay(
|
||||
'popup-evidence',
|
||||
evidence_title,
|
||||
_popup_list_html(all_evidence_bullets, floor=220, ceiling=520),
|
||||
)
|
||||
comparison_popup_html = _popup_overlay(
|
||||
'popup-comparison',
|
||||
comparison_title,
|
||||
_popup_comparison_table(comparison_rows),
|
||||
)
|
||||
|
||||
intro_html = (
|
||||
'<div style="background:linear-gradient(135deg,#fff5f5 0%,#ffe8e8 100%); border:2px solid #f8a4a4; border-radius:12px; padding:10px 14px;">'
|
||||
'<div style="background:linear-gradient(135deg,#fff5f5 0%,#ffe8e8 100%); border:2px solid #f8a4a4; border-radius:12px; padding:12px 16px;">'
|
||||
'<div style="display:flex; gap:12px; align-items:flex-start;">'
|
||||
'<div style="font-size:24px; line-height:1; color:#f59e0b; margin-top:2px;">⚠</div>'
|
||||
'<div style="flex:1;">'
|
||||
f'<div style="font-size:12px; font-weight:900; color:#b42318; margin-bottom:5px;">{problem_title}</div>'
|
||||
f'<ul style="font-size:9px; line-height:1.45; color:#7a271a; padding-left:0; margin:0 0 4px 0; list-style:disc;">{problem_items_html}</ul>'
|
||||
f'<div style="font-size:8.5px; line-height:1.38; color:#9a3412; margin-top:2px;"><span style="font-weight:800;">{evidence_title}</span></div>'
|
||||
f'<ul style="font-size:8.5px; line-height:1.38; color:#9a3412; padding-left:0; margin:2px 0 0 0; list-style:disc;">{evidence_items_html}</ul>'
|
||||
'<div style="margin-top:8px; background:#991b1b; color:#ffffff; border-radius:4px; padding:5px 10px; font-size:10px; font-weight:800; word-break:keep-all;">→ 각 용어의 정의, 역할, 상호관계에 대한 체계적 정립 필요</div>'
|
||||
f'<div style="font-size:12.5px; font-weight:900; color:#b42318; margin-bottom:6px;">{problem_title}</div>'
|
||||
f'<ul style="font-size:9.4px; line-height:1.5; color:#7a271a; padding-left:0; margin:0 0 6px 0; list-style:disc;">{problem_items_html}</ul>'
|
||||
f'<div style="font-size:9px; line-height:1.42; color:#9a3412; margin-top:4px;"><span style="font-weight:800;">{evidence_title}</span></div>'
|
||||
f'<ul style="font-size:8.9px; line-height:1.42; color:#9a3412; padding-left:0; margin:2px 0 0 0; list-style:disc;">{evidence_items_html}</ul>'
|
||||
f'{_popup_button("popup-evidence", "?? ???")}'
|
||||
'<div style="margin-top:8px; background:#991b1b; color:#ffffff; border-radius:4px; padding:5px 10px; font-size:10px; font-weight:800; word-break:keep-all;">→ ? ??? ??, ??, ????? ?? ??? ?? ??</div>'
|
||||
'</div>'
|
||||
'</div>'
|
||||
'</div>'
|
||||
@@ -586,28 +658,31 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
|
||||
f'<div style="font-size:14px; font-weight:900; color:#1f3b63; margin-bottom:6px;">{relation_title}</div>'
|
||||
'<div style="display:grid; grid-template-columns:250px 1fr; gap:14px; align-items:start;">'
|
||||
'<div>'
|
||||
f'{_relation_visual(image_src, image_caption).replace("height:220px", "height:208px").replace("padding:10px", "padding:12px")}'
|
||||
f'{_relation_visual(image_src, image_caption).replace("height:220px", "height:210px").replace("padding:10px", "padding:12px")}'
|
||||
f'<div style="margin-top:8px; background:#dcfce7; border:1px solid #86efac; color:#166534; font-size:9px; line-height:1.3; border-radius:999px; padding:4px 10px; text-align:center;">{image_caption}</div>'
|
||||
'</div>'
|
||||
'<div style="display:flex; flex-direction:column; gap:8px;">'
|
||||
f'<ul style="font-size:8.8px; line-height:1.42; color:#334155; padding-left:0; margin:0; list-style:disc;">{relation_items_html}</ul>'
|
||||
f'<ul style="font-size:9px; line-height:1.46; color:#334155; padding-left:0; margin:0; list-style:disc;">{relation_items_html}</ul>'
|
||||
'<div style="margin-top:4px; border:1px solid #b9d3ff; border-radius:10px; overflow:hidden;">'
|
||||
'<div style="display:grid; grid-template-columns:1fr 86px 1fr; background:linear-gradient(135deg,#0d47a1,#1565c0); color:#fff; font-weight:800; font-size:12px; text-align:center;">'
|
||||
'<div style="padding:7px 10px;">DX</div>'
|
||||
'<div style="padding:7px 6px; background:rgba(0,0,0,0.14); font-size:11px;">\uad6c\ubd84</div>'
|
||||
'<div style="padding:7px 6px; background:rgba(0,0,0,0.14); font-size:11px;">??</div>'
|
||||
'<div style="padding:7px 10px;">BIM</div>'
|
||||
'</div>'
|
||||
f'{comparison_rows_html}'
|
||||
'</div>'
|
||||
f'{_popup_button("popup-comparison", "??? ?? ??")}'
|
||||
'</div>'
|
||||
'</div>'
|
||||
'</div>'
|
||||
)
|
||||
|
||||
body_html = (
|
||||
'<div style="width:100%; height:100%; box-sizing:border-box; font-family:Segoe UI,sans-serif; color:#0f172a; display:flex; flex-direction:column; gap:6px;">'
|
||||
'<div style="width:100%; height:100%; box-sizing:border-box; font-family:Segoe UI,sans-serif; color:#0f172a; display:flex; flex-direction:column; gap:8px;">'
|
||||
f'{intro_html}'
|
||||
f'{relation_html}'
|
||||
f'{evidence_popup_html}'
|
||||
f'{comparison_popup_html}'
|
||||
'</div>'
|
||||
)
|
||||
|
||||
@@ -628,7 +703,7 @@ def _build_stage2_retry_html(ctx: PipelineContext, retry_plan: dict) -> dict:
|
||||
'body_html': body_html,
|
||||
'sidebar_html': sidebar_html,
|
||||
'footer_html': footer_html,
|
||||
'reasoning': 'retry regrouping by content importance: grouped problem+evidence, reference-like relation block, comparison embedded under relation, numbered definition cards',
|
||||
'reasoning': 'retry regrouping by content importance: grouped problem+evidence with popup details, relation block, visible comparison summary with full popup, numbered definition cards',
|
||||
}
|
||||
|
||||
|
||||
@@ -766,3 +841,4 @@ async def main() -> None:
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user