
    lLj>              	       J   d Z ddlZddlZddlZddlZddlmZ ej                  j                  d e
 ee      j                               ddlZddlZ ed      Z ee      j                  Zej&                  dz  dz  Zej&                  dz  dz  Zed	z  Zd
j-                  g d      Zdddddiddiddiddiddidg ddddddiddiddiddidg ddddidg ddZd
j-                  g d      Zd
j-                  g d      ZdZd Zd Zd Zd Ze dk(  r e        yy)u6  s21 blocking fp — 샷별 staging 마킹 fp(i2i) + 그 fp 를 참조에 추가한
스틸 재생성 비교 (사용자 지시, 2026-07-07).

  - 기반 = ⑯-2 산출(out/blockset/fpflat_marked_gpt.png — 완전 수직 fp +
    원형 알파벳 A~P 구조 마커, 원본 stairfix_nb2 계보).
  - 단계:
    ① 샷별 LLM(gpt) staging 저작 — 그 샷에 실제 등장하는 캐릭터/엔티티
      (동물 포함)의 top-down 위치와 카메라 위치·바라보는 방향을 알파벳
      요소 기준 상대 서술로. 발명 금지(무인이면 빈 배열)+evidence 인용.
      판단=LLM, 코드=조립만.
    ② gpt-image-2 edit: ⑯-2 fp 를 그대로 보존 + 원형 숫자(엔티티)와
      카메라 쐐기+화살표만 추가 — 샷당 1장. 마커 스타일=⑯-2 의
      원형 마커 계약(STYLE_2D_CIRCLED) 어휘 재사용.
    ③ nb2 스틸: s21_remake_bg 확정본(plans/outdoor_remake_bg.json)의
      프롬프트 **그대로**+같은 참조 구성(배경=stairfix_nb2 치환,
      스케치 제외분 유지)에 ② blocking fp 를 라벨드 참조로 **끝에 추가**
      (기존 image N 번호 보존). 새 참조 의미는 라벨 텍스트가 전달.
  - 산출: out/shots_outdoor/blocking/<샷>_blockfp.png + _blockstill.png,
    plans/outdoor_blocking_fp.json, blocking_fp.html(8897 — 3열 비교:
    원본/1차 배경교체/blocking, 샷별 fp+카메라+엔티티 작게).
  - DB write 0, 커밋 금지(scratchpad).
사용: backend/.venv/bin/python s21_blocking_fp.py         --shots S4_Shot1,S10_Shot5,S11_Shot4,S13_Shot3,S17_Shot1
    N)Pathz*/Users/manta/Documents/Projects/TheRoad-I1shots_outdoorblockingblocksetzfpflat_marked_gpt.pngzblocking_fp.html
)z,You are a film staging planner. You receive:zD- PLAN ELEMENTS: the lettered elements (circled letters) of a strictz3  top-down exterior site plan of one real location.z,- SHOT DATA: one shot's heading/description.zA- SHOT PROMPT: the full image-generation prompt actually used forz1  that shot (ground truth for what is on screen). zCTask: author the top-down STAGING for this exact shot on that plan.zC1. List every character/entity PHYSICALLY PRESENT ON SCREEN in thisuG      shot per SHOT PROMPT / SHOT DATA only — people, animals, vehicles,zD   other movable subjects. Do NOT invent anyone; permanent structurezD   already on the plan is NOT an entity; if the shot is unmanned thezD   list is empty. Refer to each by a generic role wording taken fromz#   the shot text (no proper names).zE2. For each entity give placement_en: its top-down position describedz?   ONLY relative to the lettered plan elements (e.g. 'on F justzC   outside J, toward G'). If the shot text does not fix a position,z:   choose the position the shot's framing implies and markz   inferred=true.zE3. Camera: give its top-down position_en (relative to letters; it mayz@   sit outside the drawn plan edge), facing_en (direction/targetz>   letters or entity digits), and height_en (ground/eye-level/z(   elevated/overhead per the shot text).uJ   4. Quote evidence_ko: the shot-text wording (원문 인용) grounding eachuC      entity and the camera. Keep every field short and factual — nozE   narrative, no mood, no invention beyond step 2's marked inference.uW   Also give notes_ko: 한 줄 한국어 요약 (이 샷에서 누가/무엇이 어디에,u,   카메라는 어디서 어디를 보는지).objectarraytypestringboolean)name_enname_koplacement_eninferredevidence_ko)r   
propertiesrequired)r   items)position_en	facing_en	height_enr   )entitiescameranotes_ko)z@The attached image is a strict top-down exterior SITE PLAN whosez>elements are identified by small plain CIRCLED LETTER markers.uD   REPRODUCE the attached plan EXACTLY — same geometry, same colours,uE   same circled letters, nothing moved, nothing redrawn — and ADD ONLYz$the shot-staging marks listed below.)zCMarker style: each added entity mark is a small plain CIRCLED DIGITzC(same graphic style as the existing circled letters), drawn once atz=its stated position. The camera is ONE small solid dark wedgezE(triangle) at its stated position with a short straight arrow showingzDits facing direction. Apart from the existing circled letters, thesezAcircled digits and the single camera wedge+arrow, add nothing: nozCtext, no words, no other markers, no legend, no compass, no people,zno objects.u  shot STAGING PLAN (top-down diagram of this same location — annotation only: NEVER draw or copy this diagram, its flat colours, markers or top-down view into the photograph): circled letters = structure identifiers; each circled digit = where that on-screen character/entity stands; the single dark wedge with arrow = the camera's position and facing direction for THIS shot. Use it only to place subjects and the camera consistently with the prompt text.c                    t         dg}| d   }|rX|j                  d       t        |d      D ]'  \  }}|j                  | d|d    d| d|d	           ) |j                  d       | d
   }|j                  d       |j                  d|d           |j                  d|d           |j                  d       |j                  t               dj	                  |      S )Nr   r   z+ENTITY MARKS (digits are identifiers only):   z. r   u    — circled digit z at: r   r   zCAMERA MARK:z- position: r   z
- facing: r   r   )BLOCKFP_HEADappend	enumerateBLOCKFP_TAILjoin)staginglinesentsiecams         s21_blocking_fp.pyblockfp_promptr*      s    2E:DBCdA&DAqLLA3b9.A! E~./1 2 ' 	R
(
C	LL 	LL<M 2345	LL:c+./01	LL	LL99U    c            	         t        j                         } | j                  dd       | j                  ddg d       | j                         }|j                  j                  d      D cg c]#  }|j                         s|j                         % }}t        j                         sJ d	t                t        j                  d
      }t        j                  |      \  }}t        j                  d      }|d   D ci c]  }|d   |
 }	}t        j                  d      d   }
|D ]  }||	v rJ d|         	 t        j                  d      }t        j!                  dd       |j"                  dv r|D ]  }||d   v r|d   |   j%                  d      r"|
|   }dj'                  ddj'                  |      z   d|d    d|d    d|	|   d   z   g      }t        j(                  d| t*        |t,              }||d   j/                  |i       d<   t        j0                  d|       t3        |||        |j"                  d v rv|D ]q  }|d   |   d   }t5        |      }||d   |   d!<   t        j0                  d|       t        j6                  d"| |t        gt        | d#z  $       t3        |||       s |j"                  d%v rt9        |d&         }|D ]  }|	|   }g }|d'   D ]I  }|j%                  d(      r|j%                  d)      r|nt:        |d*   z  }|j=                  |d+   |f       K |j=                  t>        t        | d#z  f       t        j@                  d,| |d   |t        | d-z  .       |d   |d   |   d/<   |D cg c]  \  }}|	 c}}|d   |   d0<   t        j0                  d|       t3        |||        t3        |||       t        jB                  d1d2|j"                  |d3       tE        d4t         d5tF                y c c}w c c}w # t        $ r t        t              i d}Y w xY wc c}}w )6Nz--shotsT)r   z--onlyall)r-   llmblockfpstillhtml)defaultchoices,u   ⑯-2 산출 없음: numbered_bd_v1outdoor_remake_bgjobsshot_keyoutdoor_shots_collectshotsu   remake plan 에 없는 샷: outdoor_blocking_fp)src_fpr:   )parentsexist_ok)r-   r.   r#   z

z-PLAN ELEMENTS (circled letters on the plan):
r   zSHOT DATA:
scene_heading: scene_headingz
description: descriptionz"SHOT PROMPT (full, ground truth):
prompts21_blocking_)r-   r/   r*   s21_blockfp__blockfp.png)refsout_path)r-   r0   new_bgrE   droppedswapped	file_pathlabels21_blockstill__blockstill.png)rF   still_promptstill_ref_labelsstages21_blocking_fp)kindrP   doner:   zdone -> z	
page -> )$argparseArgumentParseradd_argument
parse_argsr:   splitstripSRC_FPexistsF	load_planS20alpha_struct	ExceptionstrOUTmkdironlygetr"   r.   BLOCK_SYSTEMBLOCK_SCHEMA
setdefault	save_plan
build_pager*   img_gptr   ROOTr   BLOCKING_REF_LABELimg_nb2runlogprintPAGE)apargss	shot_keysresalpha_linesalpha_legendremakejr7   collectkplanuserr#   pbglabeledrpathl_s                         r)   mainr      sd   		 	 	"BOOIO-OOHeF  H==?D$(JJ$4$4S$9G$9qQWWY$9IG==?<3F8<<?
++&
'C # 0 0 5K[[,-F&,Vn5nAjM1nD5kk127;GDy<8<<y 4{{01 IIdTI* yyN"ADM!d7mA&6&:&:9&E
A;;@))K()-a.@-A B  !- 0135Q8II  D eemA3/t(*G9@DM$$Q+I6KK-t4tY5 $ yy&&A7mA&y1Gw'A12DM!-.KK-t4IIQC(!6("s,%779tY5  yy$$&"#AQAGvY55#UU9-r4!K.3H'
D12	 
 NN.<6H0HIJIIs+Qx['"s/%::</0{DM!^,BI3J'$!QA'3JDM!/0KK-t4tY5   tY-HHg(9499 " #	HSED6
*+K H 6  4f+34b 4Ks*   +PP P$=P) Q)QQc                 J   d d>fd	}dj                  fd|D              }g }|D ]  }| d   j                  |      xs i }|j                  d      }|s|j                  d |       d       Kd	dj                  fd
t        |d         D              }	|d   }
|j                  dj                  g d |       d |d          d |dt	        | |       d       d |d| dd       d |d| dd       d |d| ddd       d |ddd       d |d d!d       d"|	xs d# d$ |
d%          d& |
d'          d( |
d)          d* |
d+          d, |j                  d-             d. |j                  d/             d0 t        j                  |j                  d1      d2d34             d5              t        j                  d6|r|d7   d8   nd d9| d:dj                  |       d;d<=       y )?Nc                 F    t        j                  t        | xs d            S )Nr   )html_modescapera   )ts    r)   _esczbuild_page.<locals>._esc   s    s17|,,r+   r   c                     t         | z  }|j                         sd| d |       dS d| d |        d |       dS )Nz<div class='u9   '><div class='pending'>생성 중…</div><p class='cap'>z
</p></div>z'><img src='z'><p class='cap'>)EXPr[   )path_relcapclsr   r   s       r)   _imgzbuild_page.<locals>._img   sc    (Nxxz"3% (&&*3i[
< =se<X/? @""&s)J8 	9r+   c              3      K   | ]C  }d  |d          d |j                  d             d |j                  d             d E yw)z<tr><td><b>letterz</b></td><td>r   	</td><td>desc_ko
</td></tr>Nre   ).0r   r   s     r)   	<genexpr>zbuild_page.<locals>.<genexpr>   sd      I <Ha d1X;'( )AEE)$%& 'AEE)$%&j	2;Gs   A	Ar:   r#   z<h2>u1   </h2><p class='pending'>staging 저작 중…</p>u$   ①②③④⑤⑥⑦⑧⑨⑩⑪⑫c              3      K   | ]U  \  }}d |    d |d          d |d          d |d          |j                  d      rdnd	 d
 |d          d W yw)z<tr><td>r   r   z (r   z
)</td><td>r   r   u    <i>(추정)</i>r   z</td><td class='ev'>r   r   Nr   )r   r&   r'   r   circleds      r)   r   zbuild_page.<locals>.<genexpr>  s      3 21 wqzl #)%&ba	l);(< =.)*+%&UU:%6!B? @"1]#345Z	A
 2s   AAr   r   z
<h2>z</h2>
<p class='note'>r   z</p>
<div class='trio'>
  zout/shots_outdoor/u$   원본 최신 스틸 (기존 배경)z
  zout/shots_outdoor/remake/z_bgswap.pngu   1차 remake (배경만 교체)zout/shots_outdoor/blocking/rM   u+   신규 (배경 교체 + blocking fp 참조)z
</div>
<div class='refrow'>
  rD   uE   blocking fp — 엔티티(원형 숫자)+카메라(쐐기·화살표)refzout/blockset/stairfix_nb2.pngu   배경 참조 stairfix_nb2z"out/blockset/fpflat_marked_gpt.pngu   ⑯-2 원본 marked fpui   
</div>
<table><tr><th>마커</th><th>엔티티</th><th>배치(top-down)</th><th>근거 인용</th></tr>
u=   <tr><td colspan='4'>무인 샷 — 엔티티 없음</td></tr>u    
<tr><td>▲</td><td>카메라 (r   u   )</td>
<td>위치: r   u   <br>방향: r   z</td>
<td class='ev'>r   u\   </td></tr></table>
<details><summary>blocking fp i2i 프롬프트 (gpt edit)</summary>
<pre>r*   us   </pre></details>
<details><summary>스틸 프롬프트 (remake 확정본 그대로) + 참조 라벨</summary>
<pre>rN   z

--- ref labels ---
rO   Fr   )ensure_asciiindentz
</pre></details>
uY  <!doctype html><meta charset='utf-8'>
<title>s21 blocking fp — 샷별 staging 마킹 fp + 스틸 재생성</title>
<style>
body{font-family:system-ui,'Apple SD Gothic Neo',sans-serif;margin:24px;
background:#fafafa;color:#222;max-width:1560px}
h1{font-size:20px} h2{font-size:16px;margin-top:36px;border-bottom:2px
solid #ddd;padding-bottom:4px}
img{width:100%;display:block;background:#fff;border:1px solid #ddd;
padding:3px;box-sizing:border-box}
.trio{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px}
.cap{font-size:12px;color:#333;margin:4px 0 10px;font-weight:600}
.refrow{display:grid;grid-template-columns:repeat(5,1fr);gap:8px;
margin:6px 0}
.refrow .cap{font-size:10.5px;color:#666;font-weight:400}
.note{font-size:13px;color:#345;background:#eef3f8;padding:6px 10px;
border-radius:6px}
table{border-collapse:collapse;font-size:12px;margin:8px 0;width:100%}
td,th{border:1px solid #ddd;padding:4px 8px;text-align:left;
vertical-align:top}
.ev{color:#666;font-size:11px}
.pending{padding:40px 10px;text-align:center;color:#999;background:#fff;
border:1px dashed #ccc;font-size:12px}
pre{white-space:pre-wrap;font-size:11px;background:#fff;border:1px solid
#e5e5e5;padding:10px}
details{margin:8px 0} summary{font-size:12px;color:#557;cursor:pointer}
</style>
<h1>s21 blocking fp — ⑯-2 수직 fp(알파벳 마커) 위에 샷별 엔티티(원형 숫자)
+카메라(쐐기·화살표) i2i → 그 fp+새 배경(stairfix_nb2)을 참조로 기존
프롬프트 그대로 스틸 재생성</h1>
<p style='font-size:12.5px;color:#556'>3열: 좌=원본 최신 스틸 / 중=1차
remake(배경만 교체) / 우=신규(배경 교체+blocking fp 참조 추가, 프롬프트
불변 — 새 참조 의미는 라벨 텍스트 전달). staging 판단=LLM(gpt),
마커 부여·조립=코드. 매핑=plans/outdoor_blocking_fp.json</p>
<details><summary>⑯-2 알파벳 범례 (A~r   uI   )</summary>
<table><tr><th>글자</th><th>요소</th><th>서술</th></tr>z</table>
</details>
r   zutf-8)encoding)r   )	r"   re   r   r    	plan_origjsondumpsrq   
write_text)r}   ru   rx   r   leg_rowssecsr|   shstent_rowsr(   r   r   s              @@r)   rj   rj      s   -9 ww I <HI IH
 D']q!'RVVIKK$tAwi (- - .877 3 ""Z.13 3 l    	!WIbn%&' 
YtQ/013YZ[	\	
 
#A3k24TUV
W 
%aS857 88 
%aS5OQVX YY ')EuMNO ,.FNOP  
LL M! N !" !%S%5 67#"8#$ #m$%&%$ '3%$ 48K8H3I2J%$K%& S'()'&*'* 266"#$%+*&+. 266.!"#/. $</. =AJJrvv()aH=J <K/0K1 	! V 	OO !-D  .:"-=h-G->>FZ H K&L M  &r+   c                 \    t        j                  d      }t        fd|d   D              S )Nr6   c              3   8   K   | ]  }|d    k(  r|d     yw)r8   	orig_fileN )r   rz   r|   s     r)   r   zplan_orig.<locals>.<genexpr>R  s'      '1Z=A% +s   r7   )r\   r]   next)r}   r|   ry   s    ` r)   r   r   O  s/    [[,-F 'v ' ' 'r+   __main__)!__doc__rT   r1   r   r   syspathlibr   r   insertra   __file__parent
forest_libr\   s20_numbered_bdr^   rl   r   rb   rZ   rq   r"   rf   rg   r   r!   rm   r*   r   rj   r   __name__r   r+   r)   <module>r      s  0    
  3tH~,,- .  89
8neeo
*	
	5	5
yy  @    &1 &1%+X$6!' 3$*H#58
   &1$h/$h/ &1	(

 X&7: 3? F yy   yy 	 	G $K,\cL' zF r+   