
    (iE!                        d Z ddlmZ ddlZddlZddlmZmZmZ ddl	m
Z
 ddlmZmZmZ  ej                  d      ZddZdd	Z	 	 	 	 	 	 	 	 	 	 	 	 dd
Z G d d      Zy)u  SceneStillNormalizer — CheckpointBundle → list[PlannedStill].

Pure 로직. DB 접근 없음. 3경로:
  1) Legacy — selected_shots 없을 때 scene당 1 still (scene_extractor_v3)
  2) V4 per-shot — 각 selected shot당 1 still (scene_extractor_v4)
  3) Unselected — shot-more에서 미선택 shot (shot_more_unselected)

visible_entities 해석을 위해 EntityMaps 주입.
    )annotationsN)AnyDictList)_normalize_scene_detail_result)CheckpointBundle
EntityMapsPlannedStillz[CLP]\d{2,3}c           	         | D cg c]<  }||j                   j                  |d      |j                  j                  ||      d> c}S c c}w )N )short_ididentity_name)short_to_idgetshort_to_name)ve_listmapssids      i/Users/manta/Documents/Projects/TheRoad-I1/backend/app/services/checkpoint_sync/scene_still_normalizer.py_resolve_ver      s^    
 	 # ""3+))--c37 	  s   AA	c                   | D ]  }t        |t              s|j                  dd      }|j                  dd      }|r0|j                  d      s|j                  j                  |d      |d<   |r&|s$|j                  j                  ||      |d<   |d   }|j                  d      s$|r"|j
                  j                  |      }|r||d<   |j                  d      r|s|j                  j                  |d      |d<    y)u   Codex P3-1 Medium: baseline parity — name→id 매핑 실패 시 빈 문자열을
    강제로 주입하지 않음 (baseline은 `if matched_id: ve_item["id"] = ...`).
    short_id는 baseline과 동일하게 `.get(ename, "")` 폴백 유지.
    r   r   r   r   N)
isinstancedictr   r   r   
name_to_idname_to_short)ve_rawr   ve_itemenamer   
matched_ids         r   _backfill_ve_dictr!   "   s    
 '4(M2.kk*b)w{{4( ,,00b9GDMu%)%7%7%;%;C%EGM"M*E{{4 U,,U3J *{{:&5"&"4"4"8"8"CGJ     c                t   ||f}|| j                   v r| j                   |   S |s|S dj                  d |D              }t        t        j	                  |            }|D ]?  }|j                  dg       D ](  }	|	j                  dd      }
|
s|j                  |
       * A |D cg c]	  }||v s| c}S c c}w )N c              3  @   K   | ]  }|j                  d d        yw)
t2i_promptr   N)r   ).0vs     r   	<genexpr>z_shot_ve.<locals>.<genexpr>E   s     ?YAEE,+Ys   outfit_assignmentscharacter_idr   )shot_director_ve_mapjoinset_BARE_ID_REfindallr   add)bundledirector_ve	scene_idxshot_idx	shot_varsktextusedr(   acidr   s               r   _shot_ver<   9   s     
HAF'''**1--88?Y??D{""4()D+R0A%%+C 1 
 '6;C#+C;666s   $	B5.B5c                  <    e Zd ZddZd	dZd
dZddZddZddZy)SceneStillNormalizerc                    || _         y )N)r   )selfentity_mapss     r   __init__zSceneStillNormalizer.__init__P   s	    	r"   c           	     l   |j                   sg S g }d}|j                  D ]  }| j                  ||||      } |j                  j	                         D ]_  \  }}|j
                  j                  |t                     }|D ]1  }|d   |v r|dz  }|j                  | j                  |||             3 a |S )Nr   
shot_index   )
sd_completedscenes_plan_sceneshot_info_by_sceneitemsselected_flag_by_scener   r.   append_unselected)	r@   r2   plannedidxssishotsselshots	            r   	normalizezSceneStillNormalizer.normalizeS   s    ""I&(A""1fc7;C   2288:IB//33B>C%,qt//R>?	  ; r"   c                \   t        |d       |j                  dd      }|j                  dg       }|j                  j                  |g       }|j                  j                  |t	                     }|D 	cg c]  }	|	d   |v s|	 }
}	|j
                  j                  |g       }|j                  d      |
rt        fd|
D        d       }|s|S |g}
|
s+|d	z  }|j                  | j                  |||||             |S d u}|rt        |      n*t        d	t        |      t        t        |
      d	      z        }t        |
      D ]Y  \  }}|d	z  }||z  }|t        |
      d	z
  k(  rt        |      n||z   }|j                  | j                  |||||| |||             [ |S c c}	w )
Nz"scene_still_normalizer._plan_scene)wherescene_indexr   t2i_variationsrD   _shot_indexc              3  4   K   | ]  }|d    k(  s|  yw)rD   N )r'   sh
result_idxs     r   r)   z3SceneStillNormalizer._plan_scene.<locals>.<genexpr>p   s     Wn<8HJ8Vns   rE   )r   r   rI   rK   r.   scene_director_venextrL   _legacylenmax	enumerate_shot)r@   rP   r2   rO   outrQ   t2i_vars	all_shotsselected_idsr]   selected_shotsr3   rT   
is_partialvars_peristartendr^   s                     @r   rH   z SceneStillNormalizer._plan_scened   s   &q0TUUU=!$55)2.--11"b9	4488SUC'0UyB|4D4T"yU..222r:UU=)
!nWnWY]^D
"VN1HCJJt||B8VSABJt+
$.3x=C3x=CPSTbPcefLg;g4h 0GAt1HCLE#$N(;a(?#?#h-UXEUCJJtzz"axc/BFKY\]^	 1
 
- Vs   7F)F)c                   |j                  d      xs |j                  d      xs g }|D cg c]  }t        |t              rd|in| }}t        || j                         t        |d f||d|j                  dd      |j                  dd      |j                  dd      t        j                  |d	
      |j                  dd      |rt        j                  |d	
      nd |j                  dd      t        j                  |j                  j                  |g       d	
      t        j                  |j                  j                  |g       d	
      d	      S c c}w )Nvisible_entitiespresent_entity_idsr   scene_extractor_v3headingr   
beat_titlerepresentative_momentFensure_asciir&   
scene_typenormal)	screenplay_scene_headingru   still_frame_promptvisible_entities_jsont2i_prompt_cinematict2i_variations_jsonry   audio_entity_idshallucination_entity_idskeystill_indexrX   t2i_composer_versioncolumns)
r   r   strr!   r   r
   jsondumpsscene_director_audioscene_director_hall)r@   rQ   rP   rg   r2   rO   r   r(   s           r   ra   zSceneStillNormalizer._legacy   s.   )*Oaee4H.IORHNO1Z3%7:q/Q>O&$)),T
!5,-EE)R,@eeL"5&'ee,CR&H)-F)O()lB(?S[tzz('OaeeeL(;$(JJv/J/J/N/NrSU/Vej$k,0JJv7Q7Q7U7UVXZ\7]lq,r

 	
 Ps   Ec                   |d   }t        |||||      }	t        |	| j                        }
|j                  dd      }|j                  d      r|j                  d      r|d   }t	        ||f||d|j                  dd      |j                  dd      |t        j                  |
d	
      |j                  dd      |rt        j                  |d	
      nd |j                  dd      ||j                  dd      |j                  d      t        j                  |j                  j                  |g       d	
      t        j                  |j                  j                  |g       d	
      dd      S )NrD   descriptionr   _user_editedrv   scene_extractor_v4rt   ru   Frw   r&   ry   rz   based_on_beatTr{   ru   r|   r}   r~   r   ry   rD   shot_descriptionr   r   r   is_selectedr   )	r<   r   r   r   r
   r   r   r   r   )r@   rQ   rP   rT   r6   r2   r3   rO   r5   ve_idsr   sfps               r   re   zSceneStillNormalizer._shot   sD   %&+r8YGVTYY/hh}b)55 QUU+B%C+,CXCR!5,-EE)R,@eeL"5&))-F)O()lB(?T]tzz)%'PcgeeL(;&$(HH]B$?!%/!:$(JJv/J/J/N/NrSU/Vej$k,0JJv7Q7Q7U7UVXZ\7]lq,r#
 	
r"   c                    |d   }t        ||f||ddd|j                  dd      ddd d||j                  dd      |j                  d      dddd	
      S )NrD   shot_more_unselectedr   r   z[]rz   r   Fr   r   )r
   r   )r@   rO   rQ   rT   r5   s        r   rM   z SceneStillNormalizer._unselected   sr    %XCR!7,. &*hh}b&A)-(*'+&&$(HH]B$?!%/!:$(,0$
 	
r"   N)rA   r	   )r2   r   returnzList[PlannedStill])r   int)r   r
   )	__name__
__module____qualname__rB   rU   rH   ra   re   rM   r\   r"   r   r>   r>   O   s      ">
(
6
r"   r>   )r   	List[str]r   r	   r   zList[Dict[str, str]])r   List[Dict[str, Any]]r   r	   r   None)r2   r   r3   r   r4   r   r5   r   r6   r   r   r   )__doc__
__future__r   r   retypingr   r   r    app.core.steps._evidence_helpersr   3app.services.checkpoint_sync._scene_still_contractsr   r	   r
   compiler/   r   r!   r<   r>   r\   r"   r   <module>r      s    #  	 " " K  bjj)D.777 7 	7
 $7 7,w
 w
r"   