
    
MjE                        d 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ddlZej$                  dz  Zej(                  dz  Zh dZdZdZd	Zd
j5                  g d      Zd
j5                  g d      Zd ZdZdZdZ dZ!d
j5                  g d      Z"d
j5                  g d      Z#d Z$d Z%d Z&d Z'd Z(d Z)d Z*d Z+e,dk(  r e*        yy)u  s23 — 지역 지도 스타일 베이스 + 촬영지만 fp 스케치 (사용자 아이디어,
2026-07-07).

  - 베이스 = s22 관계 데이터(결정론 검증 통과 좌표)를 **지도 문법**으로
    결정론 PIL 렌더: 도로/골목=흰 띠+회색 케이싱, 이웃=무마커 회색 블록,
    촬영지(마커 요소)=옅은 채움+원형 문자+주황 파선 경계 하이라이트.
  - i2i = 촬영지 영역만 상세 fp 스케치로 재작도(gpt edit/nb2), 지도 부분
    은 원본 유지 — fp 어휘=기존 S15.STYLE_2D 계약 재사용, 마커=지정 원형
    문자만(⑯-2 계약 어휘).
사용: backend/.venv/bin/python s23_map_fp.py [--only all|base|sketch|html]
산출: out/blockset/bd_map_base.png + bd_map_fp_{gpt,nb2}.png, map_fp.html
    N)Pathblocksetzmap_fp.html>   roadalleyneighbor_masszbd_map_base.pngzbd_map_fp_gpt.pngzbd_map_fp_nb2.png
)<The attached image is a NEIGHBOURHOOD MAP around one filming?location, drawn straight-down. The filming property is the areaz<inside the dashed boundary, whose parts carry circled letterz>markers. REDRAW ONLY that property area as a detailed top-downz@architectural floor-plan sketch, keeping every block's position,z=size, proportions and boundary openings exactly where the mapzdraws them.z7EVERYTHING OUTSIDE the dashed boundary (roads, unmarkedz?neighbour blocks, background) stays in the original simple flatz MAP style, completely unchanged.z<Keep each circled letter marker exactly in place; apart fromz;these circled letters add no text, no words, no numbers, nozlegend, no compass.@   STRICT VERTICAL TOP-DOWN ONLY — no 3D, no axonometric tilt, nofacades, no shadows.)z9This property is an OUTDOOR urban site: open areas (yard,z7terrace, roof surfaces, alley) are OPEN-AIR ground/roofu?   surfaces — never rooms; do NOT wrap them in walls, do NOT addz<interior partitions, furniture, gardens, lawns, fountains orz<planting that is not listed below. Every enclosed unit staysu4   sealed — outer shell and its listed openings only.c                    t         j                  }|j                  d      d   j                         }| d   D ci c]  }|j	                  d      |d    }}|d   D cg c]0  }|d   t
        vr#|d   |v r||d       d|d	    d
|d    d|d    2 }}dj                  t        t        ddj                  |      z   d|z   g      S c c}w c c}w )NNeutral document:r   elements_idmarkerkindidz. name_en (u   ) — desc_ko

ul   KEY ELEMENTS (identity of each marked part — markers are identifiers only, draw each part as WHAT IT IS):
r   4Floor-plan drafting language for the property area:
)	S15STYLE_2DsplitstripgetCONTEXT_KINDSjoinMAP_FP_NOTEMAP_FP_EXTERIOR)layoutrelstylecoreemkidents          s23_map_fp.pysketch_promptr*   ?   s   LLE;;*+A.446D-3J-?	@-?!%%,(
#-?B	@*oB%&	.1T7b= 1T7}Bq|nBqyk)~N% 
 B ;;	>
))E
	 	@$F  	 
ABs   C5Czmap_pure_gpt.pngzmap_pure_nb2.pngzmapfp_pure_gpt.pngzmapfp_pure_nb2.png)
z9Draw ONE straight-down NEIGHBOURHOOD MAP in clean digitalz=street-map language: white roads with thin grey casings, flatz<pale building blocks on a paper-tone background, strictly 2Du=   top-down — no 3D, no perspective, no shadows, no labels, noztext, no icons, no compass.z>The FILMING PROPERTY parcel is the subject: draw its parts perz=the STRUCTURE lines below, and outline the parcel once with az=thin dashed boundary. Surrounding context stays simple: plainz?full-scale neighbouring blocks and the approach road/alley onlyz&(edge blocks may be cut by the frame).)r	   r
   z?inside the dashed boundary. REDRAW ONLY that property area as az@detailed top-down architectural floor-plan sketch, keeping everyz>block's position, size, proportions and openings exactly wherezthe map draws them.z@EVERYTHING OUTSIDE the dashed boundary (roads, neighbour blocks,z8background) stays in the original simple flat MAP style,zcompletely unchanged.z9Add no text, no words, no numbers, no legend, no compass.r   r   c                  T    t        j                  d      } dj                  | d         S )Nnumbered_bd_v1r   numbered_structure_en)F	load_planr   )ress    r)   _minimal_linesr1   u   s&    
++&
'C99S0122    c                  F    dj                  t        dt               z   g      S )Nr   z/STRUCTURE (the property and its surroundings):
)r   MAP_STYLE_NOTEr1    r2   r)   pure_map_promptr6   z   s)    ;;:

	  r2   c                      t         j                  } | j                  d      d   j                         }dj	                  t
        t        dt               z   d|z   g      S )Nr   r   r   ud   KEY ELEMENTS (identity of the property's parts — draw each as WHAT IT IS, positions per the map):
r   )r   r   r   r   r   MAP_FP_NOTE_PUREr!   r1   )r$   r%   s     r)   pure_fp_promptr9      s]    LLE;;*+A.446D;;	13A3C	D?$F  r2   c                     t               } t               }	 t        j                  d      }t
        | ft        | ft        |ft        |ffD ]
  \  }}|||<    t        j                  d|       t                t        j                  d| d t        t
        z         t                t        j                  d| g t        t        z         t                t        j                  d|t        t
        z  gt        t        z         t                t        j                  d|dt        t        z  fgt        t        z         t                y # t        $ r i }Y ,w xY w)	Nspatial_promptss23_pure_map_gptrefsout_paths23_pure_map_nb2r?   s23_pure_fp_gpts23_pure_fp_nb2u   NEIGHBOURHOOD MAP with the filming property inside the dashed boundary — redraw ONLY the property area as a floor-plan sketch per the prompt; keep the map part unchanged.)r6   r9   r.   r/   	ExceptionPURE_MAP_GPTPURE_MAP_NB2PURE_FP_GPTPURE_FP_NB2	save_plan
build_pageimg_gptOUTBimg_nb2)pmpfpromptsfnps        r)   run_purerS      s+   		B		B++/0  $|R&8#k2%68A8 KK!7+LII "4l*,LII "b4,3FGLII4,+>*?k)+LII  $l24 5 k)+ L/  s   E	 	EEc                  h    t        j                  d      } | d   d   }|d   rJ d       |d   |d   fS )Nbd_code_rel_v1rounds
violationsu:   마지막 라운드에 위반 잔존 — s22 먼저 수렴r"   r#   )r.   r/   )planrs     r)   load_solvedr[      sE    ;;'(DXrA\ \\X;%  r2   c                 
  &'() ddl m}m}m& d\  ('t	        d(z  'dz  z         t	        d(z  'dz  z   dz         }}|j                  d||fd      }|j                  |      }d8&fd		}'(fd
))fd}	| d   }
|
D cg c]  }|d   t        v s| }}|
D cg c]  }|d   t        vs| }}|D ]%  }|d   dv s|j                   |	|      ddd       ' |D ]&  }|d   dk(  s|j                   |	|      ddd       ( |D cg c]  }|d   t        j                  v s| }}|D cg c]  }|d   t        j                  vs| }}|j                  d        |D ]  }|d   dk(  r|j                   |	|      ddd       n|j                   |	|      ddd       |d   dk(  sL|d   |d   }}t        dt	        t        |d    |d!                     }t        d"|      D ]  }||z  }|d    |d!   k\  r=|j                   )||d    |z  z   |       )||d    |z  z   ||d!   z         gdd"#       P|j                   )|||d!   |z  z          )||d    z   ||d!   |z  z         gdd"#         |D ]A  }|d   dk(  r|j                   |	|      d$dd       '|j                   |	|      d$dd       C d%\  }}}}|D ]m  }|d   dk(  r|d   |d    dz  z
  |d   |d!   dz  z
  }}n
|d   |d   }}t!        ||      t!        ||      }}t        |||d    z         t        |||d!   z         }}o d&} )||z
  ||z
         )||z   ||z         c\  }}\  }}d'\  } }!|}||k  rY|j                  ||ft!        ||!z   |      |fgd(d#       |j                  ||ft!        ||!z   |      |fgd(d#       || z  }||k  rY|}||k  rY|j                  ||f|t!        ||!z   |      fgd(d#       |j                  ||f|t!        ||!z   |      fgd(d#       || z  }||k  rY |d)d*      }"|D ]  }|d   dk(  r )|d   |d         \  }#}$n$ )|d   |d    dz  z   |d   |d!   dz  z         \  }#}$d+}%|j                  |#|%z
  |$|%z
  |#|%z   |$|%z   gdd,d       |j#                  |#|$f|d-   |"d.d/0        |j#                  'd1fd2 |d3d*      d45       |j%                  |       t'        d6|        y7c c}w c c}w c c}w c c}w )9uI   결정론 지도 스타일 렌더 — 좌표=s22 솔버 산출 그대로.r   )Image	ImageDraw	ImageFont)   .   d      $   RGBz#f4f1eac                     dD ]  }	 j                  || |rdnd      c S  j                         S # t        $ r Y :w xY w)N)z#/System/Library/Fonts/Helvetica.ttcz,/System/Library/Fonts/Supplemental/Arial.ttf   r   )index)truetyperD   load_default)szboldrR   r_   s      r)   fontzrender_map.<locals>.font   sW    BA ))!RDqa)HHB %%''  s   3	??c                 *    | z  z   dz   |z  z   fS )N   r5   )xyMSs     r)   pxzrender_map.<locals>.px   s"    1q5y!b&1q5.((r2   c                     | d   dk(  r| d   | d   dz  z
  | d   | d   dz  z
  }}n
| d   | d   }} ||       || d   z   || d   z         gS )Nshapecirclerp   wrc   rq   hr5   )r&   rp   rq   rt   s      r)   rect_pxzrender_map.<locals>.rect_px   ss    W:!S6AcFQJ&#3!(;qAS61S6qA1a"Q3ZQsV455r2   r   r   )r   r   z#ffffffz#c9c4b8   )filloutlinewidthr   z#e6e2d8z#cfc9bbc                     | d   | d   z   S )Nrx   ry   r5   )r&   s    r)   <lambda>zrender_map.<locals>.<lambda>   s    #30r2   )keyrv   rw   z#fdfbf4z#8a8578stairrp   rq      rx   ry   rg   )r|   r~   z#f3efe4)    eAr       er   g?)      z#d2691e   Tr   z#222r   z#111mm)rm   r|   anchor
   u;   AREA MAP + filming property (dashed) — code-rendered baser   z#444)rm   r|   zmap base -> N)F)PILr]   r^   r_   intnewDrawr   	rectangleS13BLOCK_KINDSsortellipsemaxrangelinemintextsaveprint)*r"   r?   r]   r^   WHimgdrm   rz   elsr&   ctxpropblockspointsx0y0nitxsysxeyerp   rq   padbx0by0bx1by1steponf_markmxmyrZ   r_   rr   rs   rt   s*                                         @@@@r)   
render_mapr      s   //DAqsQwQS1Wq1u_r%9!:qA
))EAq69
-CsA()6 
C
8cQvY-71cC
8=s!ai}<AsD= V9))KK
I  ! 
 V9'KK
I  ! 
 >A6coo!=aF>BA6#//!AaFB
KK0K1W:!IIgajy)1IMKK
I  !V9sVQsVBAs3qvqv./0A1a[ES6QsV#FFBrAcFQJ3rAcFQJQsV<> )  4 FFBr2#
?3rAcF{B3!O<> )  4 ! & W:!IIgajy)1IMKK
I  !	  *NBBW:!S6AcFQJ&#3!(;qAS61S6qARSQZBRQsV$c"a!C&j&9B  CS"s(3RS"s(5KJS#
cHD"A
c'	C3q2vs+S12!L	C3q2vs+S12!L	T	 c' 	A
c'	a3AFC 012!L	a3AFC 012!L	T	 c' "d^FW:!##'FB#3!+QsVafqj-@AFB			262626262  	 	+	Bx86tL  FFAr7 b$f  6HHX	L

#$c 9= ?Bs0   ?S7S7S<+S<
T%T/T
Tc                     t        j                         } | j                  ddg d       | j                         }|j                  dk(  r$t                t        j                  dddd       y t               \  }}|j                  d	v rKt        t        z  }|j                         r|j                  t        d
z         t        ||       t                |j                  dv rt        ||      }	 t        j                   d      }||t$        <   ||t&        <   t        j(                  d|       t                t        j*                  d|t        t        z  gt        t$        z         t                t        j,                  d|dt        t        z  fgt        t&        z         t                |j                  dk(  r
t                t        j                  dd|j                  d       y # t"        $ r i }Y w xY w)Nz--onlyall)r   basesketchpurehtml)defaultchoicesr   stage
s23_map_fp)r   r   done)r   r   zbd_map_base_prev.png)r   r   r;   s23_map_fp_gptr=   s23_map_fp_nb2u   NEIGHBOURHOOD MAP with the filming property inside the dashed boundary — redraw ONLY the property as a floor-plan sketch per the prompt; keep the map part unchanged.rA   r   )argparseArgumentParseradd_argument
parse_argsonlyrS   r.   runlogr[   rL   BASEexistsrenamer   rJ   r*   r/   rD   SK_GPTSK_NB2rI   rK   rM   )apargsr"   r#   r   rR   rP   s          r)   mainr   $  s   		 	 	"BOOHeE  G==?DyyF
	'L&IJ-KFCyyO#d{;;=KK55664 yy%%&#&	kk"34G 	%w/			"ATD[M&=	*			"A" $($;0 1  &=	* 	yyFHHgdiiHI%  	G	s   /G) )G76G7c                     d fd	 t        j                  d      fdfdfd} t        j	                  d | dt
        t               d	 | d
t        t               d t        d       d t        d       d	 t        d       d t        d       dd       t        dt                y # t        $ r i Y w xY w)Nc                 F    t        j                  t        | xs d            S )N )_htmlescapestr)r   s    r)   _esczbuild_page.<locals>._escN  s    ||CRL))r2   c           	         t         | z  }|j                         sd |       dS dd l}|j                  j                  |j	                         j
                        }d|  dt        |j                                d |       d|dd		S )
NuC   <div><div class='pending'>생성 대기/중…</div><p class='cap'>
</p></div>r   z<div><img src='out/blockset/z?v=z'><p class='cap'>r   z%H:%M:%Sz)</p></div>)rL   r   datetimefromtimestampstatst_mtimer   	timestamp)rQ   capfr   tsr   s        r)   cellzbuild_page.<locals>.cellQ  s    2Ixxz&&*3i[
< =,,QVVX->->?.rd#c",,.6I5J K""&s)Br(m;H 	Ir2   r;   c                 X    j                  |       }|rd |       d |       dS dS )Nz<details><summary>u(    프롬프트 (실전송)</summary><pre>z</pre></details>r   )r   )rQ   titlerR   r   proms      r)   pdetzbuild_page.<locals>.pdet`  sE    HHRL@A %T%[M 2""&q'*:< 	JGI	Jr2   c                 l    t         | z  }|j                         sd |       dS d|  d |       dS )Nz<span class='mini'>u   : 대기</span>z'<div class='th'><img src='out/blockset/z'><p class='mini'>r   )rL   r   )rQ   r   r   r   s      r)   thumbzbuild_page.<locals>.thumbe  sI    2Ixxz(c?CC9" >##'9+Z9 	:r2   c                     d|  d|  d |d       d |d       d|  d |d	|  d
       d |d       d |d       dS )Nz

<h2>lane uo    — 과정</h2>
<div class='proc'>
  <div class='step'>
    <p class='stept'>STEP 1 — 무참조 T2I 지도 (uJ   )
      <span class='noref'>참조 없음(프롬프트만)</span></p>
    uH   지도 (지도 문법 계약 + v12 미니멀 구조 줄 + 파선 경계)z
    u   STEP 1 지도u   
  </div>
  <div class='arrow'>→ i2i</div>
  <div class='step'>
    <p class='stept'>STEP 2 — 촬영지(파선 안)만 fp 상세화 (z)</p>
    <div class='refrow'>u   참조 = STEP 1 지도 ()z</div>
    uS   촬영지만 상세 fp — 지도 부분 원본 유지, 정체 주입+실외 봉인u   STEP 2 상세화z
  </div>
</div>
r5   )engmap_fnfp_fnr   r   r   s      r)   lanezbuild_page.<locals>.lanel  s    

 7 8;e <	&\]^ _	&/"# $H ILu Mv)A#a'HIJ K	%fgh i	%#$% & 	r2   u  <!doctype html><meta charset='utf-8'>
<title>s23 — 무참조 지도 → 촬영지만 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:28px;border-bottom:2px
solid #ddd;padding-bottom:4px}
img{width:100%;display:block;background:#fff;border:1px solid #ddd;
padding:6px;box-sizing:border-box}
.cap{font-size:12px;color:#333;margin:4px 0 12px;font-weight:600}
.grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.proc{display:grid;grid-template-columns:1fr 46px 1fr;gap:10px;
align-items:start}
.arrow{font-size:14px;font-weight:700;color:#666;text-align:center;
padding-top:180px}
.stept{font-size:13px;font-weight:700;color:#234}
.noref{background:#234;color:#fff;font-size:11px;padding:2px 8px;
border-radius:4px;margin-left:6px}
.refrow{display:flex;gap:8px;margin:4px 0}
.th{width:130px} .th img{padding:2px}
.mini{font-size:10.5px;color:#667;margin:2px 0}
.note{background:#fff8e6;border:1px solid #eeddaa;padding:10px 14px;
font-size:13px}
.old{opacity:.75;border:2px dashed #bbb;padding:10px 14px;margin-top:40px}
.pending{padding:60px 10px;text-align:center;color:#999;background:#fff;
border:1px dashed #ccc}
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>s23 — ① 아무 참조 없이 그 지역을 "지도처럼" T2I → ② 그 지도 위에
i2i 로 촬영지(옥탑방 부지)만 상세 fp 화</h1>
<div class='note'>사용자 정정 반영: 코드 렌더 참조 X — <b>STEP 1 은 완전
무참조 T2I</b>(지도 문법 계약+v12 미니멀 구조 줄+촬영지 파선 경계),
<b>STEP 2 는 STEP 1 지도만 참조</b>해 파선 안 촬영지만 fp 상세화(정체
주입+실외 봉인, fp 어휘=S15.STYLE_2D). 엔진별 lane 독립(gpt→gpt /
nb2→nb2). 각 단계의 참조 이미지(작게)와 실전송 프롬프트 병기.</div>
gptr   nb2u   
<div class='old'>
<h2 style='margin-top:0'>(참고 — 사용자 정정으로 대체된 1차 시도: 코드
렌더 베이스를 참조로 사용)</h2>
<div class='grid'>
u+   코드 렌더 지도 베이스 (s22 좌표)z
<div>u%   gpt edit — 참조: 코드 베이스u$   nb2 i2i — 참조: 코드 베이스z</div>
</div>
u   1차 시도 스케치z
</div>
zutf-8)encodingzpage -> )r.   r/   rD   PAGE
write_textrE   rG   rF   rH   r   r   r   r   )r   r   r   r   r   r   s    @@@@@r)   rJ   rJ   M  s    *I{{,-J
:( 	OO %J e\;' ( )e\;' ( )
 d9: ; <
6:;< =f45 6 7f%& ' (_1b c  1d 
HTF
k  s   B? ?CC__main__)-__doc__r   r   r   syspathlibr   pathinsertr   __file__parent
forest_libr.   s13_blockset_v2r   s15_fp_redor   OUTrL   EXPr   r   r   r   r   r   r    r!   r*   rE   rF   rG   rH   r4   r8   r1   r6   r9   rS   r[   r   r   rJ   __name__r5   r2   r)   <module>r     s"     
  3tH~,,- .   uuzuu}2		 ii  * ))  ( "!""   99    3
	>!m%`&JReP zF r2   