
    
i                         d Z ddlZddlZddlmZmZ ddlmZ ddlm	Z	m
Z
mZmZ ddlmZ ddlmZ ddlmZmZ  ej(                  e      Zd	Zd
Z G d de      Zy)u   Shot별 촬영 기법 선정 — selected shot에 대해 technique 2개씩 배정.

DB shot_type 테이블에서 30개 촬영 기법을 로드하고,
15 shots씩 번들로 묶어 병렬 처리.
    N)ThreadPoolExecutoras_completed)Path)AnyDictListOptional)
StepRunner)call_structured)load_promptload_schema      c                   D    e Zd ZdZdedee   fdZddeeef   fdZ	d Z
y)	ShotCinematographyStepu"   Shot별 촬영 기법 2개 선정.step_idreturnc                     ddl m} t        |j                        | j                  z  dz  dz  | j
                  z  |z  dz  }|j                         r%t        j                  |j                  d            S y )Nr   )settingscheckpointsepisodeszmanifest.jsonzutf-8)encoding)
app.core.configr   r   projects_dir
project_id
episode_idexistsjsonloads	read_text)selfr   r   cps       ]/Users/manta/Documents/Projects/TheRoad-I1/backend/app/core/steps/shot_cinematography_step.py_load_prev_checkpointz,ShotCinematographyStep._load_prev_checkpoint   su    ,&&'$//9()+/??;'( 	
 99;::bllGl<==    c                     | j                  d      }|r!|j                  di       j                  d      sddlm}  |ddd	      | j                  d
      }i }|rO|j                  di       j                  d      r.|d   d   D ]#  }t	        |j                  dg             ||d   <   % g }|d   d   D ]  }|d   }|j                  |      }	|j                  dg       D ]s  }
|	|
j                  d      |	v s|j                  ||j                  dd      |
j                  dd      |
d   |
j                  dg       |
j                  dd      d       u  |s
dddg dddS ddlm} | j                  j                   |d            j                         }dj                  d |D              }t        dd| j                        }t        dd| j                        }t        dd| j                        }g }t        dt        |      t               D ]  }|j                  |||t         z            t"        j%                  d t        |      t        |             i }t'        t(        !      5 }t+        |      D ci c]-  \  }}|j-                  | j.                  ||d"z   ||||      |d"z   / }}}t1        |      D ]  }|j3                         \  }}}|||<    	 d d d        g }t5        |      D ]  }|j7                  ||           t"        j%                  d#t        |             t        |      t        |      t9        dt        |      t        |      z
        |t        |      ddS c c}}w # 1 sw Y   xY w)$Nshot_validatordatascenesr   )AppErrorzstep.no_shotsu   shot_extract 결과 없음i  )codemessagestatus_codeshot_selectionselected_shot_indicesscene_indexshots
shot_indexscene_heading description
charactersbased_on_beat)r0   r3   r2   r5   r6   r7   )r1   total_shots)completed_countapplicable_countfailed_countr(   )textzmSELECT name, category, description, llm_description FROM shot_type WHERE is_active = true ORDER BY sort_order
c           
   3   P   K   | ]  }d |d    d|d    d|d    d|d       yw)	z- r    [   z]:    z | Camera:    N ).0rs     r#   	<genexpr>z2ShotCinematographyStep._execute.<locals>.<genexpr>K   sA      %
 1b1c!A${1Q4&9s   $&shot_cinematographysystem)dbusercine_schemau5   shot_cinematography: %d selected shots → %d bundles)max_workersr@   z'shot_cinematography: %d shots processed)r$   getapp.core.errorsr*   setappend
sqlalchemyr<   rI   executefetchalljoinr   r   rangelenBUNDLE_MAX_SHOTSloggerinfor   MAX_WORKERS	enumeratesubmit_call_bundler   resultsortedextendmax)r!   modeshot_cpr*   sel_cpselected_maps	all_shotssiselected_indicesshsql_text	shot_rowsshot_types_blockrH   user_templateschemabundlesiresults_by_idxpoolbfuturesfutidxr1   errall_resultss                               r#   _executezShotCinematographyStep._execute$   s   ,,-=>gkk&"599(C09Ucfgg++,<=fjj,00:F^H-14QUU;RTV5W1XQ}-. . 	*A=!B+//3eeGR(#+rvvl/CGW/W$$'))*)C&(ff\1&=')-'8&(ff\2&>)+)C&  ) + '(aQR&(;= = 	0GGOOHH%
  8: 	  99 %
%
 

 2HI#$96dggN2MdggN q#i.*:;ANN9Qq+;';<= < 	KSQZ^]`ah]ijK8D
 &g.	 /DAq %%q!a%P`q5 /	   $G,"%**,UC&+s# - 9 'A~a01 ( 	=s;?OP  #;/ #I3y>C4D#DE)#k:JK	
 	
! 98s   /M4>2M.0,M4.M44M=c                 (   g }|D ]O  }dj                  |d         }	|d   rd|d    nd}
|j                  d|d    d|d	    d
|
 d|d    d|	 d       Q |j                  |dj                  |            }|dz  }d|d   d    d|d   d    }d}t        |dz         D ]s  }	 t	        d|||| j
                  d| | j                               }|j                  dg       }t        j                  d||t        |      t        |             ||d fc S  y # t        $ ro}||k  r7t        j                  d|||dz   ||       dd l}|j                  d       Y d }~t        j                  d||||       |g t        |      fcY d }~c S d }~ww xY w) Nz, r6   r7   zbeat:u   원문zScene r0   z Shot r2   z (z): r5   r?   ]r=   )rm   shots_blocku   
[다양성 규칙] 같은 씬의 연속 shot에 동일한 촬영 기법을 배정하지 마세요. 시각적 다양성을 위해 서로 다른 기법(category 포함)을 선택하세요.
Sr   z-S   r@   rG   
shot_cine_)stepsystem_promptuser_promptresponse_schemaproject_configschema_nameopik_metadatar1   z6shot_cinematography call %d (%s, %d shots): %d resultsz0shot_cinematography call %d (%s) retry %d/%d: %srA   z<shot_cinematography call %d (%s) FAILED after %d retries: %s)rT   rP   formatrU   r   r   build_opik_metadatarM   rX   rY   rV   	Exceptionwarningtimesleepstr)r!   bundlecall_idxrH   rn   ro   rm   shots_linesrj   charsbeatr   scene_range	max_retryattemptr^   r1   excr   s                      r#   r]   z#ShotCinematographyStep._call_bundlet   s   BIIb./E464GU2o./0XDM*+6"\2B1C2dV3m$%Rwa1  $**-		+. + 

 	h	

 &)M232fRj6O5PQ	Y]+G.(."( +$*#'#6#6",XJ 7"&":":"< 

7B/T$k3v;E
L,, ,  	.Y&NN#U#+['A+yRUWJJqM]'iFSX--	.s%   &A.D	F"7F&FFFN)resume)__name__
__module____qualname____doc__r   r	   r   r$   r   rz   r]   rC   r%   r#   r   r      s8    ,	S 	Xd^ 	N
c3h N
`..r%   r   )r   r   loggingconcurrent.futuresr   r   pathlibr   typingr   r   r   r	   app.core.step_runnerr
   app.modules.llm.llm_clientr   app.modules.prompt_loaderr   r   	getLoggerr   rX   rW   rZ   r   rC   r%   r#   <module>r      sR   
   ?  , , + 6 >			8	$ L.Z L.r%   