
    'Ej                     0   d Z ddlZddlZ ej                  e      ZddlmZmZm	Z	 ddl
mZmZ ddlmZ ddlmZ ddlmZmZmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZ ddlm Z  ddl!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z.  eddg      Z/ddde0de0de1dz  fdZ2de"de3de1fdZ4e/jk                  de6e*         d ee       ee       ee      fde0dz  de0dede fd        Z7e/jk                  d!e+       ee       ee       ee      fd"e0de0dede fd#       Z8e/js                  d!e*       ee       ee       ee      fd"e0d$e,d%e	de0dede fd&       Z:e/jk                  d'       ee       ee       ee      fde0de0dede fd(       Z;e/js                  d)e-       ee       ee       ee      fd*e0d$e.d%e	de0dede fd+       Z< G d, d-e      Z=e/js                  d.       ee       ee       ee      fd*e0d/e3d$e=de0dede fd0       Z> G d1 d2e      Z?e/j                  d3       ee       ee      fd$e?de0de fd4       ZAe/j                  d5       ee       ee      fd$e?de0de fd6       ZBe/jk                  d7       ee       ee       ee      fde0dede fd8       ZCe/js                  d7       ee       ee       ee      fd%e	de0dede fd9       ZDe/jk                  d:       ee       ee       ee      fde0dede fd;       ZEy)<u'   엔티티 및 씬 스틸 API 라우터.    N)	APIRouterDependsRequest)	BaseModelField)Session)func)get_dbget_current_userverify_project_access)AppError)build_name_indexlookup_name)t)ActivityLogger)UserAccount)EntityCanonEntityAliasEntityEpisodeLinkEpisodeRelationFactRelationParticipant
SceneStill)EntityResponseEntityDetailResponseEntityUpdateSceneStillResponseSceneStillUpdatez/api/v1/projects/{project_id}entities)prefixtagsupdated_fields
project_id
episode_idr#   c                   	 ddl m} ddlm} ddl}ddl}ddl}	 ||j                        | z  dz  dz  |z  dz  dz  }
|
j                         sy|j                  |
j                  d	
            }|j                  di       j                  dg       D ]G  }|j                  d      |k(  s|j                  d      }||k7  r/d|d<   |r|j                  |        n |j                  t        |
j                        d      \  }}	 |	j!                  ||j#                  |dd      j%                  d	             |	j'                  |       |	j)                  |t        |
             y# t*        $ rR |	j-                  |      s|	j'                  |      nd |	j.                  j                  |      r|	j1                  |        w xY w# t*        $ r Y yw xY w)ut   scene_detail 체크포인트에서 해당 shot 결과에 _user_edited=true 마킹 + 편집값 반영 (atomic write).r   PathsettingsNcheckpointsepisodesscene_detailmanifest.jsonzutf-8)encodingdatascenesscene_index_shot_indexT_user_editedz.tmp)dirsuffixF   )ensure_asciiindent)pathlibr(   app.core.configr*   jsontempfileosprojects_direxistsloads	read_textgetupdatemkstempstrparentwritedumpsencodeclosereplace	Exceptionget_inheritablepathunlink)r$   r%   r2   
shot_indexr#   r(   r*   _jsonr=   r>   cp_pathcpscp_shotfdtmps                   I/Users/manta/Documents/Projects/TheRoad-I1/backend/app/api/v1/entities.py_mark_checkpoint_user_editedrZ   +   s   $ , &&'*4()+56./ 	
 ~~[[**G*<=#''"5Auu]#{2%%.($(.!!HH^, 6 ""s7>>':6"JC	HHRReAFMMgVWHHRLJJsCL) 	 " 2 22 6BHHRLDww~~c"		#		
  s4   AG AG *AG AE& &AGG 	GGcanonepisode_countreturnc                     | j                   | j                  | j                  | j                  | j                  | j
                  xs d| j                  | j                  || j                  d
S )Nz{})
idshort_identity_typenamedescriptionstable_traits
t2i_promptstatusr\   
created_at)	r_   r`   ra   rb   rc   rd   re   rf   rg   )r[   r\   s     rY   _entity_to_responserh   T   s]    hhNN((

((,,4&&,,&&&     z	/entities)response_modeltypedbcurrent_userc                 6   |j                  t              j                  t        j                  |k(        }| r"|j                  t        j                  | k(        }|j                  t        j                        j                         }g }|D ]  }|j                  t        j                  t        j                              j                  t        j                  |j                  k(        j                         xs d}|j                  t        ||              |S )Nr   )queryr   filterr$   ra   order_byrb   allr	   countr   r_   canon_idscalarappendrh   )	rk   r$   rl   rm   ro   canonsresultsr[   ep_counts	            rY   list_entitiesrz   c   s     HH[!(()?)?:)MNE[44<=^^K,,-113FGHHTZZ 1 4 456V%..%((:;VX 	 	
 	*5(;<  Nri   z/entities/{entity_id}	entity_idc                 	   |j                  t              j                  t        j                  | k(  t        j                  |k(        j                         }|st        dt        d      d      |j                  t        j                  t        j                              j                  t        j                  |j                  k(        j                         xs d}|j                  t              j                  t        j                  |j                  k(        j                         D cg c]  }|j                   }}|j                  t               j                  t         j                  |j                  k(        j                         }g }	t#               }
|D ]  }|j$                  |
v r|
j'                  |j$                         |j                  t(              j                  t(        j                  |j$                  k(        j                         }|s~|j                  t               j                  t         j$                  |j                  k(        j+                  t         j,                        j                         }g }|D ]  }|j                  t              j                  t        j                  |j                  k(        j                         }|j/                  |r|j0                  n|j                  |j                  |j2                  |j,                  d        |	j/                  |j                  |j4                  |j6                  |j8                  |j:                  |j<                  |j>                  |d        |j                  t              j                  t        j                  |j                  k(        j                         }g }|D ]  }|j                  t@              j                  t@        j                  |jB                  k(        j                         }|sS|j/                  |j                  |jD                  |jF                  d        tI        ||      }||d<   |	|d	<   ||d
<   |S c c}w )Nentity.not_found  codemessagestatus_coder   )entity_namer{   roleorder)r_   relation_familyrelation_typedirectionalitytemporal_scopecontinuity_prioritycontinuity_reasonparticipants)r%   episode_numbertitlealiases	relationsr,   )%ro   r   rp   r_   r$   firstr   r   r	   rs   r   rt   ru   r   rr   aliasr   setrelation_idaddr   rq   participant_orderrv   rb   participant_roler   r   r   r   r   r   r   r%   r   r   rh   )r{   r$   rl   rm   r[   ry   ar   participationsr   seen_relation_idspfactall_participantsparticipant_listrpparticipant_canonep_linksr,   linkepbases                         rY   
get_entityr   z   s    		)+[-C-Cz-Q	R	 

 #()
 	
 	-0012	!**ehh6	7	 
	  +&	$$0	1	A 	
   	$%	#,,8	9	 
 I==--amm,xx%,,\__-MNTTV HH()V'33tww>?X);;<SU	 	 "B%"++56 
 ##9J055PRP[P[[[++--	%  # 	''#33!//"11"11#'#;#;!%!7!7,	
 		= V 	"#	!**ehh6	7	 
 HXXg%%gjjDOO&CDJJLOO ee"$"3"3   uh/DDO!DDKYs   ,Q?bodyrequestc           
         |j                  t              j                  t        j                  | k(  t        j                  |k(        j                         }|st        dt        d      d      |j                  r|j                  j                  nd }i }i }	|j                  /|j                  |d<   |j                  |_
        |j                  |	d<   |j                  /|j                  |d<   |j                  |_        |j                  |	d<   |j                  /|j                  |d<   |j                  |_        |j                  |	d<   |j                  /|j                  |d<   |j                  |_        |j                  |	d<   dd	lm}
m} |
j!                  |j"                        j%                         |_        |j)                          t+        |      }|j-                  |j                  d
d| |||	d|       |j                  t/        j0                  t2        j                              j                  t2        j4                  |j                  k(        j7                         xs d}t9        ||      S )Nr}   r~   r   rb   rc   rd   re   r   datetimetimezonezentity.updateentitybeforeafteractor_idactionresource_typeresource_idr$   detail
ip_address)ro   r   rp   r_   r$   r   r   r   clienthostrb   rc   rd   re   r   r   nowutc	isoformat
updated_atcommitr   logr	   rs   r   rt   ru   rh   )r{   r   r   r$   rl   rm   r[   ipr   r   r   r   loggerry   s                 rY   update_entityr      s    		)+[-C-Cz-Q	R	 

 #()
 	
 !(		DBFEyyvYY
		f# % 1 1} ,,#//m%"'"5"5"00!%!3!3o"$//|??"ool+||HLL1;;=EIIKBF
JJ 51   	-0012	!**ehh6	7	 
	  uh//ri   z/episodes/{episode_id}/stillsc                 N(   |j                  t              j                  t        j                  |k(  t        j                  | k(  t        j
                  dk\  t        j                  dk7        j                  t        j
                        j                         }ddl	m
}m} dd l}t               }|D ]x  }		 t        j                  |	j                   xs d      }
|
D ]M  }t%        |t&              r%|j)                  d      xs |j)                  dd      nd}|s=|j+                  |       O z i }|ra|j                  |      j                  |j,                  j/                  |            j                         }|D ci c]  }|j,                  | }}|j                  |      j                  |j                  |k(        j                         }i }|D ]f  }|||j0                  |j2                  f<   |||j0                  df<   |j,                  |vr|||j,                  <   |j+                  |j,                         h i }|r}|j                  |      j                  |j4                  j/                  |      |j6                  dk(  |j8                  d	k(        j                         }|D ci c]  }|j4                  | }}|D ch c]  }||v s||   j2                  d
k(  s| }}i }|r|j                  |      j                  |j4                  j/                  |      |j6                  dk(        j                  |j:                  j=                               j                         }|D ]Y  }|j4                  |vs|j>                  r-d|j>                  vs-d|j>                  vs<d|j>                  vsK|||j4                  <   [ |j                  |      j                  |j                  |k(  |j2                  d
k(        j                         }|D ci c]  }|j0                  | }}ddl	m } i }|j                  |      j                  |j                  |k(  |j                  | k(        j                         }|D ]  }|jB                  xs d||jD                  <   ! tG        |D cg c]  }|j2                  d
k(  s| c}d       }tG        |D cg c]  }|j2                  dk(  s| c}d       } i }!|D ]q  }"|"jH                  s|"jH                  |!v rEtJ        jM                  d|"jH                  ||!|"jH                     j,                  |"j,                         c|"|!|"jH                  <   s g }#|D 	]J  }	tO        jP                  |	      jS                         }$	 t        j                  |	j                   xs d      }%|	jT                  xs ddz   |	jV                  xs dz   }&g }'|	jX                  r 	 t        j                  |	jX                        }'|'D ].  })t%        |)t&              s|&d|)j)                  d      xs dz   z  }&0 i }*|'D ]  })t%        |)t&              s|)j)                  d      xs g D ]  }+t%        |+t&              s|!j)                  t]        |+j)                  d      xs d            },|!j)                  t]        |+j)                  d      xs d            }-|,q|-t|*j_                  |,j0                  |-j0                           |ja                  d|&      D ]2  }.|*j_                  |.jc                  d	      |.jc                  d             4 |ja                  d|&      D ]X  }.|.jc                  d	      |.jc                  d      }0}/|/|!v r|!|/   j0                  n|/}1|0|!v r|!|0   j0                  n|0}2|1|*vsT|2|*|1<   Z g }3t               }4t        |je                  d|&            }5t        |je                  d|&            }6|*jg                         D ]n  \  }1}2ti        ||1      }7ti        | |2      }8|7s"|1|4vs'|4j+                  |1       d }9|7r|8r|j                  |      j                  |j4                  |7j,                  k(  |j6                  dk(  |j>                  jk                  d|7j,                   d |8j,                   d!            jm                         }9|9s|7r|j)                  |7j,                        }9|3jo                  |7j,                  |7jH                  |8r|8jH                  nd |1 d"|2 d#|1|8r|8j,                  nd |7jp                  xs d|9d u|9r|9j,                  nd |j)                  |7j,                  d      d$       q |3D ch c]  }|d   	 }:}|5|6z  D ]  };|!j)                  |;      }<|<r|<j,                  |:v r%|:j+                  |<j,                         |j)                  |<j,                        }=|3jo                  |<j,                  |<jH                  |<j0                  |<j2                  |<j0                  |<jp                  xs d|=d u|=r|=j,                  nd |j)                  |<j,                  d      d%	        |%D ]j  }>t%        |>t\              r|j)                  |>      }?n}t%        |>t&              rk|j)                  |>j)                  d      xs |>j)                  d      xs d      }?|?4|>j)                  d&      r#|!j)                  |>j)                  d&            }?nd }?|?|?j,                  |:v r|?j2                  d
k(  r|?j0                  |4v r|4j+                  |?j0                         |:j+                  |?j,                         |j)                  |?j,                        }@|3jo                  |?j,                  |?jH                  |?j0                  d
|?j0                  |?jp                  xs d@d u|@r@j,                  nd |j)                  |?j,                  d      d%	       |?j2                  d'v s|:j+                  |?j,                         |j)                  |?j,                        }A|3jo                  |?j,                  |?jH                  |?j0                  |?j2                  |?j0                  |?jp                  xs dAd u|ArAj,                  nd |j)                  |?j,                  d      d%	       m |3|$d(<   g }B|$j)                  d)      }C|Cr|j                  t              j                  t        j,                  Ck(        jm                         }D|Dr|j                  |      j                  |jr                  Dj,                  k(  |j6                  d*k(  |j8                  d	k(        jm                         }EBjo                  |Dj,                  |Dj
                  |Djt                  |Djv                  |Djx                  xs dDjz                  xs dEd u|ErEj,                  nd d+       B|$d,<   g }Fd-D ]~  }G|$j)                  d.|G d/      }H|HsHd0k7  s!Fjo                  Gj}                         H|$j)                  d.|G d1      |$j)                  d.|G d2      |$j)                  d.|G d3      d4        F|$d5<   |#jo                  |$       	M g }I|D cg c]  }|j2                  dk(  s| }J}|JD ]W  }K|j)                  |Kj,                        }LIjo                  |Kj,                  |Kj0                  |Ld u|LrLj,                  nd d6       Y i }M	 dd7l?m@}N dd8lAmB}O  |O|Nj                        |z  d9z  d:z  | z  }P|Pd;z  d<z  }Q|Pd=z  d<z  }R|Pd>z  d<z  }S|Qj                         rt        j                  Qj                               }Ti }URj                         rkt        j                  Rj                               }V|Vj)                  d?i       j)                  d@g       D ]#  }Wt        |Wj)                  dAg             U|WdB   <   % i }XSj                         rbt        j                  Sj                               }Y|Yj)                  d?i       j)                  d@g       D ]  }W|Wj)                  dCg       X|WdB   <    Tj)                  d?i       j)                  d@g       D ]  }Z|ZdB   }[Uj)                  |[      }\g }]|Zj)                  dDg       D ]J  }^]jo                  |^dE   |^dF   |^j)                  dGg       |^j)                  dHd      \d u xs ^dE   \v dI       L ]Xj)                  [g       t        Zj)                  dDg             t        dJ |]D              dKM|[<    |#D ]E  }_|_j)                  dB      _j)                  dB      n_j)                  dM      }[|[9[Mv s>M[   _dN<   G |!jg                         D ;ci c]  \  };}|;|j0                   }`};}ddOl	mH}a g }b|j                  |a      j                  |aj                  |k(        j                         }c|cD ]  }d|j)                  |dj                        }e|j)                  |dj                        }f|erfs?|j                  |      j                  |j4                  dj                  k(  |j6                  dk(  |j>                  jk                  d|dj                   d |dj                   d!            jm                         }gbjo                  |dj                  ej0                  |dj                  fj0                  |gd u|grgj,                  nd dP        |#Ib`dQS # t        j"                  $ r g }
Y w xY wc c}w c c}w c c}w c c}w c c}w c c}w # t        j"                  $ r g }%Y w xY w# tZ        $ r,}(tJ        jM                  d|	j,                  |(       Y d }(~(d }(~(ww xY wc c}w c c}w # tZ        $ r!}(tJ        jM                  dL|(       Y d }(~(d }(~(ww xY wc c}};w )RNr   stale)r   
ImageAsset[]r_   r{    	reference   	characterzoutlook_id:zoutfit:z
composite:)r   c                     | j                   S Nrb   es    rY   <lambda>zlist_stills.<locals>.<lambda>      ri   )key_fnoutlookc                     | j                   S r   r   r   s    rY   r   zlist_stills.<locals>.<lambda>  r   ri   z8Duplicate short_id=%s in project %s: kept %s, skipped %s uF   t2i_variations_json parse failed for still %s: %s — 본문만 사용re   outfit_assignmentscharacter_id
outlook_idz\[\[([^\]]+)\]\+\[([^\]]+)\]\]r7   z(C\d{2,3})(O\d{2,3})z(?<![A-Z])P\d{2,3}(?!\d)zL\d{2,3}z%composite::%+	composite)r{   r`   outlook_short_idr   ra   display_namer   re   has_reference_imagereference_image_idt2i_appearance_count)	r{   r`   r   ra   r   re   r   r   r   r`   )proplocationresolved_entitiesdependent_scene_idscene)still_idstill_indexr2   rQ   shot_description
beat_title	has_imageimage_iddependent_scenes)r   b
variation__typenone_angle_color_reason)labelrk   anglecolorreason
variations)r   outlook_namer   r   r)   r'   r+   r,   shot_validatorr.   shot_selectionbeat_extractr0   r1   selected_shot_indicesr2   beatsshotsrQ   rc   
charactersbased_on_beat)rQ   rc   r   r  selectedc              3   D   K   | ]  }|j                  d       sd  yw)r  r   N)rC   ).0rU   s     rY   	<genexpr>zlist_stills.<locals>.<genexpr>  s     )V[AEE*DU![s     )r   r   total_shotsselected_countzFailed to load shot data: %sr   
shots_info)CharacterOutlook)r   character_namer   r   r   r   )stillsavailable_outfitsavailable_compositesentity_sid_map)Kro   r   rp   r$   r%   r   rf   rq   rr   app.models.projectr   r   rer   r<   rA   visible_entities_jsonJSONDecodeError
isinstancedictrC   r   r_   in_rb   ra   r{   
asset_type
is_primaryrg   descprompt_usedr   r   rt   r   r`   r   warningr   model_validate
model_dumpstill_frame_promptt2i_prompt_cinematict2i_variations_jsonrM   rF   
setdefaultfinditergroupfindallitemsr   liker   rv   re   r   r2   rQ   r   r   upperr;   r*   r:   r(   r?   r@   rB   lensumr	  r   r   )hr%   r$   rl   rm   r  r   r   _reall_entity_idsstillvisveid
entity_mapr   r   all_project_entitiesentity_name_mapprimary_image_mapprimary_imagesimgchar_entity_idschar_face_image_mapchar_ref_imagesall_project_charscchar_name_mapr   _t2i_count_map	_ep_links_lnk_char_name_idx_outlook_name_idx_short_id_map_eresultr0   vis_listt2i_text	_t2i_varsexc_vchar_to_outlook_oa_c_ent_o_ent_mc_sido_sidc_nameo_namer   
seen_charst2i_prop_sidst2i_loc_sidsc_canono_canoncomposite_img
_seen_eidssidr   ref_img_ve_ve_ent_face_refr   dep_scene_id	dep_stilldep_imgr   label_suffixvtyper  outlook_entitiesol
outfit_img
shots_data	_settings_Pathcp_baseshot_cp_pathsel_cp_pathbeat_cp_pathshot_cp_datasel_datasel_cp_datarU   	beat_databeat_cp_datascsir  scene_shotsshitemr  r	  r  co_linkscochar_entoutlook_entcomp_imgsh                                                                                                           rY   list_stillsr|  '  s    		!!Z/!!Z/""a'(	

 
*((	)	  ; UN	**U88@DAC A=G4=P155;8!%%R"8VXC""3'   J88K(//0B0B>0RSWWY'/0x!addAgx
088K0778N8NR\8\]aacO!34/0()%44z! Jqtt144  " *-44  $$^4!![0!!Q&
 #%	 	
 <JJ>CS]]C/>J '5ynsz8IjY\oNiNimxNxsnOy((:.55  $$_5!![0
 (:((--/
0 	 #C}}$77=+OT]ehetetTt  zF  NQ  N]  N]  z]9<'6 # -44*,;. 
ce  )::(91QVVQY(9M: 5N*+22$$
2$$
2 
ce  (,(A(A(FQt}}%  &(I(qAMM[,H(IN )(G(qAMMY,F(G M"{{;;-'NNJZr{{)C)F)F %'bkk" # F!007BBD	zz%"="="EFH
 ,,2c9U=W=W=][]^	$$x JJu'@'@A	 B"d#C266,#7#=2>>  Bb$'34::!#t,&**3sww~/F/L"+MN&**3sww|/D/J+KL%&*<#..v{{FKKH ;  ,,@(KB&&rxx{BHHQK@ L ,,6AB88A;5E27=2H]5)..eF27=2H]5)..eF_,*0' B U
 CKK(CXNO3;;{H=> .335NFF!.&9G!"3V<G63v& $w$&HHZ$8$?$?",,

:"--<"..33k'**QwzzlZ[4\]% eg	 "
 %$7$;$;GJJ$GM!((!( ' 0 0<C(8(8&,XQvh#7#.$*07'**T")"4"4":+8+D>K-*:*:QU,:,>,>wzz1,M*  6: /@@.?an.?
@!L0C"&&s+FVYY*4NN699%'++FII6G$$#YY"OO%{{%11 &$//52'.d':4;gjj(6(:(:699a(H
& 
 1* C#s#$..-C&$..)=)T)TRTU?swwz':+//
0CDG'**
":""k1<<:-w||,wzz*+//

;!((!( ' 0 0#*<<#.$+LL")"4"4":+0+<6;%((,:,>,>wzz1,M
* 
 $$(<<wzz*(,,WZZ8!((!( ' 0 0#*<<#*#6#6$+LL")"4"4":+/t+;59$''t,:,>,>wzz1,M
* 
? V %6 ! xx 45,33JMM\4QRXXZIHHZ(V"++y||;"--8"--2
 UW  !'' )#,#8#8#,#8#8"+"6"6(1(B(B(Hb"+"6"6"<"!(!4.5

4	) 	 $4  
&LHHz,u=>E&!!)//1!!XX
<.&GH!XX
<.&GH"hhL>'IJ#  ' (\dC H #7V#7a1==I;U#7V&**2551
  %%GG#4/)3
	"
 	  J,<9)	../*<}LzY\ff !11OC 00?B//A ::l&<&<&>?LH!!#"jj)>)>)@A$4882FA14QUU;RTV5W1XHQ}-. G I""$#zz,*@*@*BC%))&"599(BGA23%%2DIa./ H #&&vr266xD&#<<+ &&"-B&&&(&6')-'8&(ff\2&>)+)C$,$4$T<8HH8T(  . )&]]2r2#&rvvgr':#;&))V[)V&V	"
2 E, (,(?(KTXXm$QUQYQYZgQh>bJ.!+BD  1>0C0C0EF0Efc1c166k0ENF 4xx()001A1L1LPZ1Z[__aH>>"//2 nnR]]3{88J'..  BOO3!![0""''+boo5FaVW(XY
 %'	 	
 	##OO&mm--',,!-'/T%
 	 ( . 4(	 s ## 	C	 1& K z& ;  	J 	H0 ## 	H	  xginiqiqsvwwxL A` Wn  <5s;;< Gs   3#AM9AM8"AM=<	ANANAN
ANAN3AN
ANAN#AN'AN2 AO*=AO/AO/7IAO4 GAP!MAM5M4AM5NAN/N.AN/N2	AO'N;!AO"O"AO'O4	APO=APPAPz/stills/{still_id}r   c           
      F   |j                  t              j                  t        j                  | k(  t        j                  |k(        j                         }|st        dt        d      d      |j                  r|j                  j                  nd}i }i }	|j                  i|j                  |d<   |j                  |_
        |j                  |	d<   t        ||j                  |j                  |j                  d|j                  i       |j                  /|j                  |d<   |j                  |_        |j                  |	d<   |j                   /|j                   |d	<   |j                   |_        |j                   |	d	<   |j"                  /|j"                  |d
<   |j"                  |_        |j"                  |	d
<   |j$                  [|j$                  |d<   |j$                  |_        |j$                  |	d<   t        ||j                  |j                  |j                         |j&                  /|j&                  |d<   |j&                  |_        |j&                  |	d<   |j(                  /|j(                  |d<   |j(                  |_        |j(                  |	d<   d|j+                  d      xs i v r/|j,                  |d<   |j,                  |_        |j,                  |	d<   |j/                          t1        |      }
|
j3                  |j                  dd| |||	d|       |S )z?Update a scene still's prompt, beat_title, camera, or lighting.still.not_foundr~   r   Nr  representative_momentr"   r   camera_jsonlighting_jsonr  t2i_prompt_closeupr  r   T)exclude_unsetzstill.updater+  r   r   )ro   r   rp   r_   r$   r   r   r   r   r   r  rZ   r%   r2   rQ   r   r  r  r  r  r  r  r   r   r   r   )r   r   r   r$   rl   rm   r+  r   r   r   r   s              rY   update_stillr    s    		
):+@+@J+N	O	 

 "'(
 	
 !(		DBFE*','?'?#$#'#:#: &*&=&="#$((%*;*;U=M=M3T5L5LM	

 "$//|??"ool# % 1 1} ,,#//m%"'"5"5"00!%!3!3o  ,).)C)C%&%)%>%>"(,(A(A$%$Z1A1A5CTCTV[VfVfg*','?'?#$#'#:#: &*&=&="#!!-*/*E*E&'&*&@&@#)-)C)C%&d C IrJ','?'?#$#'#:#: &*&=&="#IIKBF
JJ 51   Lri   c                       e Zd ZU eed<   y)T2IVariationUpdatere   N)__name__
__module____qualname__rF   __annotations__ ri   rY   r  r    s    Ori   r  z,/stills/{still_id}/t2i-variation/{var_index}	var_indexc                    |j                  t              j                  t        j                  | k(  t        j                  |k(        j                         }|st        ddd      t        j                  |j                  xs d      }|dk  s|t        |      k\  rt        ddd	      |j                  ||   d
<   t        j                  |d      |_	        |j                          t        ||j                  |j                   |j"                         ddlm}  ||||j                        j)                          d|dS )u&   T2I 변형 프롬프트 개별 수정.r~  u   씬을 찾을 수 없습니다r~   r   r   r   zstill.invalid_indexu   잘못된 변형 인덱스i  re   Fr8   )EpisodeProjectionServiceT)okvariation_index)ro   r   rp   r_   r$   r   r   r<   rA   r  r'  re   rI   r   rZ   r%   r2   rQ   app.services.checkpoint_syncr  sync_t2i_appearance_counts)	r   r  r   r$   rl   rm   r+  r   r  s	            rY   update_t2i_variationr  !  s    HHZ ''!:#8#8J#Feg 
 -7WehiiE55=>J1}	S_41;Wehii*.//Jy,' $

:E JEIIK !U-=-=u?P?PRWRbRbc FRU-=-=>YY[955ri   c                   .    e Zd ZU  eddd      Zeed<   y)T2ITranslateRequest.r   i  )
min_length
max_lengthre   N)r  r  r  r   re   rF   r  r  ri   rY   r  r  E  s    CA$?J?ri   r  z/t2i/translate-to-koreanc                     ddl m}  |dd| j                  d      }dt        |t              r|j                         iS | j                  iS )u>   T2I 프롬프트를 한국어로 번역 (엔티티 ID 보존).r   	call_textt2i_translationu  T2I 이미지 생성 프롬프트를 한국어로 번역하세요.
중요 규칙:
- C01O02, C13, P03, L05 같은 엔티티 ID 패턴은 절대 번역하지 마세요. 원본 그대로 유지하세요.
- [L07: description] 같은 배경 표기도 그대로 유지하세요.
- [Camera: ...] 같은 촬영 지시도 그대로 유지하세요.
- 'Photorealistic cinematic still.' 같은 스타일 접두어도 그대로 유지하세요.
- 나머지 영어 묘사만 자연스러운 한국어로 번역하세요.皙?stepsystem_promptuser_prompttemperaturekorean_promptapp.modules.llm.llm_clientr  re   r  rF   stripr   r$   rm   r  rB  s        rY   translate_t2i_to_koreanr  I  sN     5Y OOF z&#/FV\\^\\DOO\\ri   z/t2i/translate-to-englishc                     ddl m}  |dd| j                  d      }dt        |t              r|j                         iS | j                  iS )uE   한국어 T2I 프롬프트를 영어로 번역 (엔티티 ID 보존).r   r  r  u  한국어 T2I 이미지 생성 프롬프트를 영어로 번역하세요.
중요 규칙:
- C01O02, C13, P03, L05 같은 엔티티 ID 패턴은 절대 번역하지 마세요. 원본 그대로 유지하세요.
- [L07: description] 같은 배경 표기도 그대로 유지하세요.
- [Camera: ...] 같은 촬영 지시도 그대로 유지하세요.
- 'Photorealistic cinematic still.' 같은 스타일 접두어도 그대로 유지하세요.
- 나머지 한국어 묘사만 자연스러운 영어로 번역하세요.r  r  re   r  r  s        rY   translate_t2i_to_englishr  c  sN     5Y OOF Jvs,C&,,.YYYYri   z/style-rulesc                 >   ddl m} ddl}|j                  |      j	                  |j
                  | k(        j                         }|r|j                  sddddS |j                  r|j                  |j                        nd|j                  |j                  xs ddS )u,   프로젝트 단위 스타일 규칙 조회.r   ProjectSettingsNX  style_rulesworld_summaryscene_split_threshold)r  r  r<   ro   rp   r$   r   style_rules_jsonrA   r  r  )r$   rl   rm   r  rR   pss         rY   get_style_rulesr    s     3	/	"	)	)/*D*D
*R	S	Y	Y	[BR((#dUXYY;=;N;Nu{{2#6#67TX))!#!9!9!@S ri   c                 2  K   ddl m} ddl}ddlm}m} |j                  |      j                  |j                  |k(        j                         }| j                          d{   }	|sc |t        t        d      j                               ||j                  |j                        j                               }|j                  |       d|	v r|j!                  |	d   d	      |_        d
|	v r
|	d
   |_        d|	v rt'        |	d         |_        |j                  |j                        j                         |_        |j-                          |j"                  r|j/                  |j"                        nd|j$                  |j(                  xs ddS 7 1w)u%   프로젝트 스타일 규칙 수정.r   r  Nr   uuid)r_   r$   r   r  Fr  r  r  r  r  )r  r  r<   r   r   ro   rp   r$   r   rF   
__import__uuid4r   r   r   r   rI   r  r  intr  r   r   rA   )
r   r$   rl   rm   r  rR   r   r   r  r   s
             rY   update_style_rulesr    sU     3+	/	"	)	)/*D*D
*R	S	Y	Y	[BD:f%++-.!||HLL1;;=

 	r
#kk$}*=EkR$0$&#&t,C'D#E LL.88:BMIIK <>;N;Nu{{2#6#67TX))!#!9!9!@S '  s   A!F#F$D1Fz/character-outlooksc           
          ddl m}m} |j                  |      j	                  |j
                  | k(        j                         }|D ch c]  }|j                   c}|D ch c]  }|j                   c}z  }i }|ra|j                  |      j	                  |j                  j                  |            j                         }	|	D 
ci c]  }
|
j                  |
 }}
g }|D ]  }|j                  |j                        }|j                  |j                        }|s<|s?|j                  |j                  |j                  |j                  |j                  |j                  xs d|j                  xs dd        |S c c}w c c}w c c}
w )u&   인물+아웃룩 조합 목록 반환.r   )r	  r   r   )r
  r   r   r   outlook_descriptionoutlook_t2i_prompt)r  r	  r   ro   rp   r$   rr   r   r   r_   r  rC   rv   rb   rc   re   )r$   rl   rm   r	  r   combosrx  all_idsent_mapentsr   rB  ry  rz  s                 rY   list_character_outlooksr    sW    A 	!"	 ++z9	:	  *002r0F3SFbBMMF3SSGGxx$++KNN,>,>w,GHLLN$()Dq1447D)F;;r/kk"--0MM"*-- ( + 0 0)nn'2'>'>'D"&1&<&<&B 	  M' 13S *s   F!FF)F__doc__r<   logging	getLoggerr  r   fastapir   r   r   pydanticr   r   sqlalchemy.ormr   
OrmSession
sqlalchemyr	   app.api.depsr
   r   r   app.core.errorsr   app.core.name_matcherr   r   app.i18n.loaderr   app.logging.activity_loggerr   app.models.catalogr   r  r   r   r   r   r   r   r   app.schemas.entityr   r   r   r   r   routerrF   r  rZ   r  rh   rC   listrz   r   patchr   r|  r  r  r  r  postr  r  r  r  r  r  ri   rY   <module>r     s   -  			8	$ / / % 0  H H $ ?  6 *    
*

 ~B &S &c &osvzoz &R{ 3 4  K^(<=34V_ '(8 9	
* 	 	 >, #4HI 34V_ '(8 9	ddd 	d 	d JdN %nE
 34V_ '(8 9A0A0
A0 A0 	A0
 	A0 A0 FA0H +, 34V_ '(8 9	YYY 	Y 	Y -Yx "3EF
 34V_ '(8 9UU
U U 	U
 	U U GUp  <=
 34V_ '(8 9666 6 	6
 	6 6 >6F@) @ '( 34 '(8 9]
]] ] )]2 () 34 '(8 9Z
ZZ Z *Z6 N34V_ '(8 9  $ n 34V_ '(8 9	### 	# 	# #L !"34V_ '(8 9!!! ! #!ri   