
    UHj=                       d Z ddlmZ ddlZddlZddlZddlZddl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  ee      j)                         j*                  d   Zed	z  Zd
ddddddddddddddddddZ ej2                  d      ZdAdZdAdZdBdZdCdDdZdEd ZdFd!Z dGd"Z!dHd#Z"dHd$Z#dId%Z$dJd&Z%dKd'Z&dLdMd(Z'dNd)Z(dOd*Z)dPd+Z*dQd,Z+dRd-Z,dSd.Z-dTd/Z.dQd0Z/dQd1Z0	 	 	 	 	 	 	 	 	 	 	 	 dUd2Z1dVd3Z2	 	 	 dW	 	 	 	 	 	 	 	 	 dXd4Z3dQd5Z4dQd6Z5dQd7Z6dQd8Z7dQd9Z8dQd:Z9dYd;Z:dZd<Z;dZd=Z<efd[d>Z=d\d?Z>e?d@k(  r e>        yy)]zLTrace event/object VM text source opcodes around the 0x0b text routine call.    )annotationsN)Counter)Path)Any)classify_cnsfind_cns_stringsread_sectionsva_to_offset   outzrender current context text id   
0x0041bb4czZpush context+0x28; call 0x0041b579; copy context+0xce/0xd2 to cursor 0xd6/0xda; advance +4zinherited context+0x28)namelengthhandlerVaHexeffectsourcez&spawn child object with text/source id   
0x0041bb99zalloc object via 0x435b5b; child+0x1c=stream u16+4; child+0x20=stream u16+6; child+0x40=stream dword+8; child+0x28=stream dword+0x0c; advance +0x14z:stream dword at +0x0c, but command-start proof is requiredzset current context text id   
0x0041bca4zscontext+0x28=stream dword+4; use low 16 bits as index into 0x55b134 to seed context+0xce/0xd2/0xd6/0xda; advance +8zstream dword at +4)         uY   [\u3131-\u318e\uac00-\ud7a3A-Za-z0-9][\u3131-\u318e\uac00-\ud7a3A-Za-z0-9 　!?.:_+-]{1,}c                    d| dS )N0x08x values    =/home/exedev/hwanse/tools/summarize_event_text_source_flow.pyhex32r"   -       c{    c                    d| dS )Nr   02xr   r   s    r!   hex8r'   1   r#   r$   c                p    | j                         s|S t        j                  | j                  d            S )Nutf-8encoding)existsjsonloads	read_text)pathdefaults     r!   	load_jsonr2   5   s*    ;;=::dnngn677r$   c                    dj                  t        | xs d      j                               j                         } t	        |       |k  r| S | d |dz
   dz   S )Nz /  r   z...)joinstr
splitlinesstriplen)textlimits     r!   compact_textr<   ;   sQ    ::c$*"o002399;D
4yE%!)u$$r$   c                f    | D ],  }|d   |cxk  r|d   |d   z   k  sn |d   |z   |d   z
  c S  y )Nrawraw_sizevar   sectionsoffsetsections      r!   va_for_offsetrE   B   sM     ;5>VJgenwz7J&JJ4=6)GEN::; r$   c                L    | D ]  }|d   |cxk  r|d   |d   z   k  s|c S  ! y )Nr@   r?   r   )rB   r@   rD   s      r!   section_for_varG   I   s@     4=BD1D!DDN E r$   c                L    | D ]  }|d   |cxk  r|d   |d   z   k  s|c S  ! y )Nr>   r?   r   rA   s      r!   section_for_offsetrI   P   s@     5>VJgenwz7J&JJN K r$   c                d    |dk  s|dz   t        |       kD  ry t        j                  d| |      d   S )Nr   r   <Ir9   structunpack_fromexerC   s     r!   dword_atrQ   W   5    zVaZ#c(*dC033r$   c                d    |dk  s|dz   t        |       kD  ry t        j                  d| |      d   S )Nr      z<HrL   rO   s     r!   word_atrU   ]   rR   r$   c                H    |y t        | |      }|y t        |      |d   dS )Nr   )targetVaHextargetSection)rG   r"   )rB   r    rD   s      r!   pointer_targetrY   c   s6    }Xu-GU|  r$   c                    t        j                  d|      }d}d}	 | j                  ||      }|dk  r|S |dz   }t        ||      |dz  }0)NrK   r   r   )rM   packfindrI   )rP   rB   targetneedlecountsearchhits          r!   pointer_ref_countrb   o   s_    [[v&FEF
hhvv&7Lqh,8QJE r$   c                   g }t               }d}t        | dz         D ]  \  }}|dv rt        |      dk\  r|j                  dd      j	                  d      }t
        j                  |      D ]h  }|j                  d      j	                         }	t        d |	D              }
t        |	      d	k\  sC|
d	k\  sI|j                  t        ||z         |	d
       j |j                          |dz   }|s|}|j                  |        g }t               }|D ].  }|d   }||v r|j                  |       |j                  |       0 |d d S )Nr       >   r   @   r   cp949ignorez  c              3  V   K   | ]!  }d |cxk  rdk  sn d|cxk  rdk  rn nd # yw)u   ㄱu   ㆎu   가u   힣r   Nr   ).0chars     r!   	<genexpr>z text_snippets.<locals>.<genexpr>   s1      ' #t7x78t;Wx;W 's   ')rT   )vaHexr:   r   r:   
   )	bytearray	enumerater9   decoder8   TEXT_REfinditergroupsumappendr"   clearsetadd)database_vasnippetscurrentcurrent_startindexbytedecodedmatchr:   hangul_countdedupedseenitemkeys                  r!   text_snippetsr   |   sW   HkGM . !t<7|q !..(;AA%H$--g6 E ;;q>//1D#& '$(' $L
 4yA~,!*; %*7]+B%C$()  MMO!AIM %NN4 +!, G5D 6l$;t 3B<r$   c           	        t        d||z
        }t        t        |       dz
  ||z         }g }t               }t	        ||dz  z
  |dz   d      D ]m  }	t        | |	      }
|
|vr|	|
f}||v r|j                  |       |j                  t        t        ||	      xs d      ||
   t        ||
         |	|z
  dd       o |d d S )Nr   r   r   nearby-cns-proximity)refVaHexr   kinddistanceevidenceStatusr   )maxminr9   rw   rangerQ   rx   ru   r"   rE   r   )rP   rB   stringsrC   radiusstartendrowsr   offr    r   s               r!   linked_cns_nearr      s    6F?#E
c#hlFVO
,CD5DUeai(#'15 c"El$;mHc:?a@EN 0f4
 	 9r$   c                   g }| D ]~  }t        |d   d      }|j                  d      xs g D ]U  }t        |d   d      }|j                  |||d   |d   |j                  d      |d   |j                  d      xs g d       W  |S )NrecordVaHex   conditionChoicesconditionVaHexmaptargets)startVaendVa
startVaHexendVaHexr   r   r   )intgetru   )event_transitionswindowsevent	record_vachoicecondition_vas         r!   route_windowsr      s    G" m,b1	ii 239r 
	Fv&67<LNN'"$%56!-0yy'$]3!::i06B 
	 Nr$   c                    g }|D ]9  }|d   | cxk  r	|d   k  sn |j                  |d   |d   |d   |d   d       ; |S )Nr   r   r   r   r   r   )r   r   r   r   )ru   )r@   r   r   windows       r!   command_route_contextr      sc    D )4VG_4KKe}%m4"("6!),	  Kr$   c                   |xs i j                  dg       D ci c]%  }|j                  d      r|j                  d      |' }}|xs i j                  dg       D ci c]  }|j                  d      r|j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d	      |j                  d
      |j                  d      d	 }}i }| xs i j                  dg       D ]F  }|j                  d      }|j                  d      }	|r|	s+|j                  |	i       }
|	|j                  d      |j                  d      |j                  d      ||j                  d      t        |j                  d      xs |j                  d      xs d      |j                  d      xs g |j                  d      xs g |j                  d      xs g |j                  d      xs g |
j                  d      |
j                  d      xs g d}|j                  |g       j                  |       I ||dS c c}w c c}w )Nr   id
flowGroupsr   r   stabilityClassconfidenceStatusremainingRiskpromptCountfirstPromptIdlastPromptId)	r   r   r   r   r   r   r   r   r   promptsrenderVaHexglobalIndexclassificationstatus	waitVaHexdisplayTextr:   r4   resourceNames	fieldMapstilesetsrouteContextsflowEvidenceClassflowGroupIds)r   r   r   r   r   r   r   r   r   r   r   r   r   )promptsByRenderflowGroupsById)r   r<   
setdefaultru   )story_promptsstory_flow_reviewrow	flow_rowsrs   flow_groupsprompts_by_renderprompt	render_va	prompt_idflow_rowentrys               r!   build_link_contextr      sg    &+00<774= 	sI " (-222<D 99T? 			$))D/IIf%99U##ii(89 %		*< ="YY7 99]3"YY7!IIn5

 
	
K  02 &B++Ir: BJJ}-	JJt$		==B/!::m4$jj)9:jj*$K0'

=(A(]VZZPVEW(][]^#ZZ8>BK06B

:.4"#ZZ8>B!).A!B$LL8>B
 	$$Y3::5A+B. -% W
s   *JB;Jc                L    | j                  d      ry| j                  d      ryy)Nr   route-window-candidate	nearbyCnsr   unboundr   r   s    r!   cns_evidence_statusr   	  s#    
ww'
ww{%r$   c                     | dk(  r	 y| dk(  r	 yy)Nr   zwcommand VA falls inside a known route-condition window, but this still does not prove story-dialogue playback by itselfr   zCNS pointers are adjacent to the text command in the local static block; treat this as resource adjacency, not a canonical map/dialogue bindingz8no CNS or route-window evidence attached to this commandr   )r   s    r!   cns_evidence_noter     s1    ))?	
 ''U	
 Fr$   c                    t        |j                  d      xs i j                  | d   g             }t        |      | d<   |d d | d<   g }t               }|D ]C  }|j                  d      xs g D ])  }||v r|j	                  |       |j                  |       + E |j                  d      xs i }|d d D cg c]  }||v r||    c}| d	<   t        |      | d
<   t        |       }|| d<   t        |      | d<   y c c}w )Nr   rl   linkedPromptCountr   linkedPromptsr   r   r   linkedFlowGroupslinkedFlowGroupCountcnsEvidenceStatuscnsEvidenceNote)listr   r9   rw   rx   ru   r   r   )	r   link_contextlinked_prompts	group_idsseen_group_idsr   group_idgroups_by_idr   s	            r!   enrich_row_linksr     s5   <++,=>D"II#g,XZ[\N">2C)#2.CIUN  '

>28b 	'H>)x(X&		''  ##$45;L "#2|# 	XC
 #&i.C %F%C.v6Cs   8C;c                   |dk(  rdddS |dk(  rt        | |dz         }d|dz   t        |       k  r| |dz      nd |dz   t        |       k  rt        | |dz            nd t        | |dz         t        | |d	z         t        | |d
z         t	        t        | |d
z               nd ||t	        |      nd |d|dz  ddd
S d dd
S t        | |dz         }d||t	        |      nd |d|dz  dddS d ddS )Nr   zinherited-contextzVopcode 0x0b carries no immediate text id; it renders the current object's context+0x28)
sourceKindsourceDescriptionr   zchild-context-streamrT   r      r   r   i  04xzDwould write stream+0x0c into the spawned child object's context+0x28)
r   	childTypechildTypeHexxy
field40HextextSourceValuetextSourceValueHextextSourceLow16Hexr   zcurrent-context-streamz6writes stream+4 into the current object's context+0x28)r   r   r   r   r   )rQ   r9   r'   rU   r"   )rP   rC   opcodetext_ids       r!   decode_payloadr   7  s]   ~-!y
 	
 ~3.0,2QJS,AVaZt5;aZ#c(5JDVaZ1PTfqj)fqj)>FsFUVJ>W>c%fqj 9:im&4;4G%.TAHATBw'7&<"=!g
 	
 [_!g
 	
 sFQJ'G."070CeGn=D=P7V#3C"89U  W[U r$   c                ^    | j                  d      ry| d   dk(  ry| d   dk(  ry| d   dk(  ry	y
)NcurrentDwordPointerzEaligned pointer byte overlap, not a proven event/object command start	opcodeHex0x0bzHplausible render command; text id is inherited from current context+0x280x0dzAplausible source command; sets current context+0x28 from stream+40x0czNcandidate child text-source command, but current hits need command-start proofunclassifiedr   r   s    r!   classify_commandr  U  sE    
ww$%V
;6!Y
;6!R
;6!_r$   c                ^    | j                  d      ry| d   dv r| j                  d      dv ryy)	Nr   lowr   >   r   r   followingByteHex>   0x000x010x020x030x04mediumweakr   r   s    r!   command_confidencer  a  s8    
ww$%
;++8J0KOw0wr$   c                   g }|D ]  }|d   dvr|d   }| |||d   z    }t         D ]  }	t        d|	g      }
d}	 |j                  |
|      }|dk  r,|dz   }||z   }|d   |z   }t        | |      }t	        d|d	z
        }t        t        |       |d
z         }i d|dt        |      d|d   dd|dd|	dt        |	      dt         |	   d   d|dz  d|t        |      nd dt        ||      dt        | ||      d|dz   t        |       k  rt        | |dz            nd dt        | ||	      dt        | |||      dt        | || t        ||      xs d      dt        ||      }t!        |      |d<   t#        |      |d<   t%        ||       |j'                  |       p  |j)                  d  !       |S )"Nr   >   .data.rdatar>   r?   re   r   r   r@         rl   rD   fileOffsetHexr   06xr   r   r   
offsetMod4r   currentDwordHexr   pointerRefCountr  rT   payloadr   nearbyTextSnippetsr   r   
confidencec                    | d   | d   fS )Nr   r@   r   r   s    r!   <lambda>zscan_commands.<locals>.<lambda>  s    s8}c$i8 r$   )r   )TEXT_SOURCE_OPCODESbytesr\   rQ   r   r   r9   r"   r'   rY   rb   r   r   r   rE   r   r  r  r   ru   sort)rP   rB   r   r   r   r   rD   	raw_startr>   r   patternr`   ra   rC   r@   r|   nearby_start
nearby_endr   s                      r!   scan_commandsr%  i  s    D '!6?"55EN	)Y)<<=) "	!FT6N+GFhhw/7q"ST]S("3/"1ftm4 S6E>:
"U2Y wv $r&%6	
 f  f #$7$?$O !&1* &9LuW~RV *>(G+L &'8h'K '!cRUhAVS!_(=\` ~c66B  h!P )-L8TVcdlnzV{  WA  @A  +B  $%:2w%G!$ )9(=$%$6s$;L! l3C ? "	!'!P 	II8I9Kr$   c                   g }| D ]  }|j                  d      r|j                  |       n|d   dk(  r|j                  |       n|j                  d      r|j                  |       nf|d   dk(  r4|j                  d      s|j                  d      r|j                  |       n*|d   dk(  r"|j                  d      r|j                  |       t        |      d	k\  s |S  |S )
Nr   r   r  r   r   r   r  r      )r   ru   r9   )r   selectedr   s      r!   selected_rowsr)    s    H 77&'OOC 'OOC WW_%OOC 'SWW[-ASWWMaEbOOC 'CGGK,@OOC x=CO Or$   c           
        t        |       }t        | |      }t        |xs g       }t        ||      }t	        | ||||      }t        d |D              }	t        d |D              }
t        d |D              }t        d |D              }|D cg c]  }|j                  d      s| }}|D cg c]  }|j                  d      s| }}|D cg c]  }|j                  d      s| }}|D cg c]  }|d   d	k(  s| }}|D cg c]  }|d   d
k(  s|d   dk(  s| }}t        d |D              }t        |      xr t        d |D              }i dddt        j                         D cg c]  \  }}dt        |      i| c}}dt        |      dt        t        |	j                                     dt        t        |
j                                     dt        t        |j                                     dt        t        |j                                     dt        |      dt        |      dt        |      dt        d |D              d|dt        |      d|j!                  d      D cg c]
  \  }}||d  c}}d!d"d#t#        |      d$|S c c}w c c}w c c}w c c}w c c}w c c}}w c c}}w )%Nc              3  &   K   | ]	  }|d      yw)r   Nr   ri   r   s     r!   rk   z build_summary.<locals>.<genexpr>  s     6#S%6   c              3  &   K   | ]	  }|d      yw)r  Nr   r,  s     r!   rk   z build_summary.<locals>.<genexpr>  s     BcL 1Br-  c              3  @   K   | ]  }|j                  d d        yw)r   r   Nr   r,  s     r!   rk   z build_summary.<locals>.<genexpr>  s     !Zc#''*=y"I!Z   c              3  J   K   | ]  }|j                  d       s|d     yw)r   r   Nr   r,  s     r!   rk   z build_summary.<locals>.<genexpr>  s!     $h#QfIgS%5$hs   #
#r   r   r   r   r  r   r  r  c              3     K   | ]F  }|j                  d i       j                  d      r#|j                  d i       j                  d       H yw)r  r   Nr   r,  s     r!   rk   z build_summary.<locals>.<genexpr>  sI      779b!%%&:; 		2""#78s   AAc              3  >   K   | ]  }|j                  d         yw)r   Nr   r,  s     r!   rk   z build_summary.<locals>.<genexpr>  s     >wbeswwG\?]>ws   scopezAevent/object VM text source flow around opcode 0x0b -> 0x0041b579handlerEffectscommandCountcommandCountsByOpcodeconfidenceCountscnsEvidenceCountspointerOverlapCountsByOpcoderouteLinkedCommandCountlinkedPromptCommandCountlinkedFlowCommandCountlinkedPromptTotalc              3  @   K   | ]  }|j                  d d        yw)r   r   Nr   r,  s     r!   rk   z build_summary.<locals>.<genexpr>  s      QS)<a!@ Qr0  opcode0cAllPointerOverlapopcode0dMediumCommandCountopcode0dTopSourceValuesr   )valueHexr_   
conclusiona	  Opcode 0x0b renders the current object's context+0x28 through text routine candidate 0x0041b579. Opcode 0x0d is the direct current-context producer seen in static byte streams, setting context+0x28 from stream+4. The three apparent opcode 0x0c child-context producer hits are aligned pointer-byte overlaps, including the two inside the confirmed map1_02b -> map1_01a condition block, so they are not promoted as executed text-source commands. This review now cross-links 0x0b render commands to wait-delimited story prompts and story-flow groups when available. CNS links are evidence-tiered: nearby-cns-proximity means static resource adjacency only, and route-window-candidate still needs dispatcher/runtime proof before it can be treated as a canonical map/dialogue binding.selectedRowsr   )r	   r   r   r   r%  r   r   boolallr  itemsr'   r9   dictsortedrt   most_commonr)  )rP   r   r   r   rB   r   r   r   r   countsconfidence_countscns_evidence_countspointer_overlap_countsr   
route_rowslinked_prompt_rowslinked_flow_rowsopcode0c_rowsopcode0d_rowssource_valuesopcode0c_all_pointer_overlapr   metar    r_   s                            r!   build_summaryrX    s+    S!HsH-G-34G%m5FGLh,GD666FBTBB!!ZUY!ZZ$$h$hh!%B#)A#BJB)-N#9L1M#NN'+Osww7M/NOO$(GSC,<,FSGMG$(iSC,<,F3|K\`hKhSiMi   M
 $(#6#w3>wiv>w;w  T  3 9 9 ;
 $v,/$/
  	D	  	 fV\\^&<!=  	D(9(?(?(A!BC  	T&)<)B)B)D"EF  	'V4J4P4P4R-S(T  	"3z?  	#C(:$;  	!#&6"7  	S QD QQ  	$%A   	%c-&8! " 	" - 9 9" =$
u /$
# * 	q- < 	d+= > 	?    CNOGi
$
sN   J)%J)/J.J.J3'J31J8?J8	J=J= J=3K
K
c                    | j                  d      xs i }| d   dk(  ry|j                  d      r|d    d|d    d|j                  d	       S |j                  d      xs d
S )Nr  r   r   zinherits context+0x28r   r    z low16=r   -r   )r   r  s     r!   command_summaryr\    sx    ggi &BG
;6!&{{'(,'('2F*G)HPWP[P[\pPqOrss;;|$++r$   c                b    | j                  d      xs g }|sydj                  d |D              S )Nr   r[  , c           
   3     K   | ]d  }|j                  d        ddj                  |j                  d      xs g       xs d d|j                  d       d|j                  d        f y	w)
r   z->,r   ?rZ  r   z..r   Nr   r5   ri   r   s     r!   rk   z"context_summary.<locals>.<genexpr>  sz       88E?
2chhtxx	':'@bAHSI488TdKeJffhimiqiqr  jA  iB  	Cs   A*A,rb  )r   contextss     r!   context_summaryre    s9    ww'-2H99   r$   c                    | j                  d      xs g }|s| j                  d      xs dS dj                  d |d d D              }| j                  dd       d| S )Nr   r   r[  r^  c           	   3     K   | ]?  }|j                  d        d|j                  dd       d|j                  dd      dd A y	w)
r   :r   ra  (r   r   z+d)Nr   rc  s     r!   rk   zcns_summary.<locals>.<genexpr>  sP       88F
Adhhvs34Adhhz16Mb5QQRSs   AAr   z: rb  )r   rH  namess      r!   cns_summaryrl    sn    GGK &BEww*+2s2II "1I E gg)3/05'::r$   c                h    | j                  d      xs g }|sydj                  d |d d D              S )Nr   r[  z; c           	   3  |   K   | ]4  }|j                  d        dt        |j                  dd      d        6 yw)r   rZ  r   r4   Z   N)r   r<   )ri   r   s     r!   rk   z!prompt_summary.<locals>.<genexpr>  s@       ::d
Al6::mR+H"MNOs   :<r   rb  )r   r   s     r!   prompt_summaryrp  
  s?    ggo&,"G99 bqk  r$   c                h    | j                  d      xs g }|sydj                  d |d d D              S )Nr   r[  r^  c              3  f   K   | ])  }|j                  d        d|j                  d        + yw)r   rh  r   Nr   )ri   rs   s     r!   rk   z%flow_group_summary.<locals>.<genexpr>  s7       99T?
1UYY'789:s   /1r   rb  )r   groupss     r!   flow_group_summaryrt    s@    WW'(.BF99 BQZ  r$   c                    g }|j                  d | j                  d      xs g D               dj                  d |d d D              xs dS )Nc              3  @   K   | ]  }|j                  d d        yw)r:   r4   Nr   rc  s     r!   rk   zrow_samples.<locals>.<genexpr>   s     XD488FB'Xr0  r  r^  c              3  &   K   | ]	  }|s|  y w)Nr   )ri   samples     r!   rk   zrow_samples.<locals>.<genexpr>!  s     @V@s   r   r[  )extendr   r5   )r   sampless     r!   row_samplesr{    sI    GNNXCGG<P4Q4WUWXX99@'"1+@@GCGr$   c                `    t        | xs d      j                  dd      j                  dd      S )Nr[  |z\|
z<br>)r6   replacer   s    r!   md_cellr  $  s+    u|$$S%088vFFr$   c                   dd| d   dd| d    dt        j                  | d   d	       d
t        j                  | d   d	       dt        j                  | d   d	       dt        j                  | d   d	       d| d    d| d    d| d    d| d    d| d    dddddg}| j                  d      xs g D ]2  }|j                  d|d    d |d!    d"|d#    d$|d%    d&|d'    d(       4 |j	                  g d)       | j                  d*      xs g D ]   }|j                  d|d+    d$|d,    d(       " | j                  d*      s|j                  d-       |j	                  g d.       | j                  d/      xs g D ]  }|j                  d|d0    d1|d    d$|d2    d&t        t        |             d&t        t        |             d&t        t        |             d&t        t        |             d&t        t        |             d&t        t        |             d(        | j                  d/      s|j                  d3       d4j                  |      d4z   S )5Nz# Event Text Source Flowr4   rD  z- commands: r6  z- by opcode: r7  Fensure_asciiz- confidence: r8  z- cns evidence: r9  z- pointer overlaps: r:  z- route-linked commands: r;  z- prompt-linked commands: r<  z- flow-linked commands: r=  z#- opcode 0x0c all pointer overlap: r@  z- opcode 0x0d medium commands: rA  z## Handler Effectsz&| opcode | handler | source | effect |z| --- | --- | --- | --- |r5  z| `r   z` r   z | `r   z` | r   z | r   z |)r4   z## Top 0x0d Source Valuesr4   z| value | count |z| --- | ---: |rB  rC  r_   z	| - | - |)r4   z## Selected Commandsr4   zl| va | opcode | confidence | cns evidence | prompts | flow groups | source | route context | text snippets |z7| --- | --- | --- | --- | --- | --- | --- | --- | --- |rE  rl   z` | `r  z%| - | - | - | - | - | - | - | - | - |r~  )r-   dumpsr   ru   ry  r  rl  rp  rt  r\  re  r{  r5   )summarylinesr   s      r!   markdownr  (  s   "


w~./0


7+B#CRWXYZ
G,>$?eTUV
4::g.A&BQVWXY
tzz'2P*Q`efgh
#G,E$F#GH
$W-G%H$IJ
"7+C#D"EF
-g6Q.R-ST
)'2N*O)PQ

0#'E* {{+,2 
#k"#2c&k]$s>7J6K48}oSXr3	


 
LL   {{45; Bs3z?+4G~R@AB;;01[!	LL   {{>*0b 
#g,uS%5$6d3|;L:MS{3'()W^C5H-I,J#)#./0GOC<P4Q3RRUs+,-SS9I1J0K2O	

 ;;~&<=99Ud""r$   c                   g }| j                  d      xs g D ]  }|j                  dt        j                  |d          dt        j                  |d          dt        j                  |d          dt        j                  |d	          d
t        j                  |d          d        dj	                  d | j                  d      xs g D              xs d}dj	                  g ddddddddddddddd d!d"d#d$d%d&d'd(d)t        j                  | d*          d+d,| d-    d.d/| d0    d.d1| d2    d.d3| d4    d.d5| d6    d.d7t        j                  t        j                  | d8   d9:             d.d;d<d=dj	                  |       d>d?d@| dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d      S )`Nr5  <tr><td><code>r   z</code><br>r   z</td><td><code>r   </code></td><td>r   z	</td><td>r   
</td></tr>r4   c              3  `   K   | ]&  }d t        j                  |d          d|d    d ( yw)r  rC  r  r_   r  N)htmlescaper,  s     r!   rk   zhtml_page.<locals>.<genexpr>l  s;       S_566Fs7|nT^_s   ,.rB  z(<tr><td colspan="2">No values.</td></tr>r~  z<!doctype html>z<html lang="ko">z<head>z  <meta charset="utf-8">zF  <meta name="viewport" content="width=device-width, initial-scale=1">z'  <title>Event Text Source Flow</title>z	  <style>z    :root{color-scheme:dark;--bg:#101214;--panel:#171a1e;--panel2:#20242a;--line:#303740;--text:#edf0f3;--muted:#aeb7c2;--accent:#7cc7ff;--warn:#ffd166;--good:#7bd88f}z    *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 system-ui,-apple-system,Segoe UI,sans-serif}z    .topbar{position:sticky;top:0;z-index:10;display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px 18px;background:#0d0f12;border-bottom:1px solid var(--line)}z    h1{font-size:20px;margin:0}h2{font-size:15px;margin:0 0 10px}nav{display:flex;gap:10px;flex-wrap:wrap}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}z    .wrap{padding:18px;display:grid;gap:16px}.panel{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:14px}.summary{color:var(--muted);max-width:1200px}a~      .metrics{display:flex;gap:8px;flex-wrap:wrap}.chip{display:inline-flex;align-items:center;gap:4px;border:1px solid var(--line);border-radius:999px;padding:2px 8px;background:var(--panel2);color:var(--muted);white-space:nowrap}.chip.good{color:var(--good);border-color:#2f6b3b}.chip.warn{color:var(--warn);border-color:#765f25}.chip.blue{color:var(--accent);border-color:#285c7e}z    .filters{display:flex;gap:10px;align-items:center;flex-wrap:wrap}input[type=search],select{background:#0f1115;color:var(--text);border:1px solid var(--line);border-radius:6px;padding:8px 10px}input[type=search]{min-width:320px;flex:1}z    .layout{display:grid;grid-template-columns:minmax(0,1fr) 420px;gap:16px;align-items:start}.tablewrap{overflow:auto;max-height:72vh;border:1px solid var(--line);border-radius:8px}a!      table{border-collapse:collapse;width:100%;background:var(--panel)}th,td{border-bottom:1px solid var(--line);padding:7px 8px;vertical-align:top;text-align:left}th{position:sticky;top:0;background:#1d2228;z-index:1;color:#dbe4ee}tr{cursor:pointer}tr:hover,tr.selected{background:#202832}a      code{color:#f2d479}.muted{color:var(--muted)}small{color:var(--muted)}pre{white-space:pre-wrap;margin:0;background:#0f1115;border:1px solid var(--line);border-radius:6px;padding:10px}.refs{display:grid;gap:8px}.ref-row{border:1px solid var(--line);border-radius:6px;padding:8px;background:#111419}.kv{display:grid;grid-template-columns:118px minmax(0,1fr);gap:6px 10px}.kv dt{color:var(--muted)}.kv dd{margin:0;min-width:0}.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}z}    @media (max-width:980px){.layout{grid-template-columns:1fr}.tablewrap{max-height:none}input[type=search]{min-width:100%}}z
  </style>z</head>z<body>u     <div class="topbar"><h1>Event Text Source Flow</h1><nav><a href="../web/index.html">관리 홈</a><a href="story_prompts.html">대사 프롬프트</a><a href="story_flow_review.html">대사 흐름</a></nav></div>z  <div class="wrap">z&    <section class="panel summary"><p>rD  z</p><div class="metrics">z"      <span class="chip">commands r6  z</span>z,      <span class="chip blue">prompt-linked r<  z*      <span class="chip blue">flow-linked r=  z+      <span class="chip warn">route-window r;  z.      <span class="chip">0x0c pointer-overlap r@  z      <span class="chip">cns r9  Fr  z    </div></section>z    <section class="panel"><h2>Handler Effects</h2><div class="tablewrap" style="max-height:none"><table><thead><tr><th>opcode</th><th>handler</th><th>source</th><th>effect</th></tr></thead>z    <tbody>z </tbody></table></div></section>z|    <section class="panel"><h2>Top 0x0d Source Values</h2><table><thead><tr><th>value</th><th>count</th></tr></thead><tbody>z    z</tbody></table></section>ad      <section class="panel"><h2>Commands</h2><div class="filters"><input id="search" type="search" placeholder="prompt id, text, cns, va, flow group"><select id="status"><option value="">all evidence</option></select><label class="chip"><input id="promptOnly" type="checkbox"> prompt-linked only</label><span id="count" class="muted"></span></div></section>aw      <main class="layout"><section class="tablewrap"><table><thead><tr><th>va</th><th>opcode</th><th>evidence</th><th>prompt</th><th>flow</th><th>cns</th></tr></thead><tbody id="rows"><tr><td colspan="6">Loading...</td></tr></tbody></table></section><aside class="panel"><h2 id="detailTitle">Detail</h2><div id="detail" class="muted">Select a command row.</div></aside></main>z  </div>z
  <script>z1    const DATA_URL='event_text_source_flow.json';z%    let data=null;let selectedKey='';z,    const $=id=>document.getElementById(id);zz    const esc=v=>String(v??'').replace(/[&<>"']/g,ch=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[ch]));zq    const short=(v,n=120)=>{v=String(v??'').replace(/\s+/g,' ').trim();return v.length>n?v.slice(0,n-1)+'...':v};z5    const keyOf=row=>`${row.vaHex}:${row.opcodeHex}`;z[    function chip(text,cls=''){return `<span class="chip ${cls}">${esc(text||'-')}</span>`}z    function statusClass(status){return status==='nearby-cns-proximity'?'warn':status==='route-window-candidate'?'blue':status==='unbound'?'':'good'}zo    function promptText(row){return (row.linkedPrompts||[]).map(p=>`${p.id} ${p.displayText||''}`).join(' | ')}zr    function flowText(row){return (row.linkedFlowGroups||[]).map(g=>`${g.id}:${g.stabilityClass||''}`).join(', ')}zb    function cnsText(row){return (row.nearbyCns||[]).map(c=>`${c.name}:${c.kind||''}`).join(', ')}z    function rowSearch(row){return [row.vaHex,row.opcodeHex,row.confidence,row.classification,row.cnsEvidenceStatus,promptText(row),flowText(row),cnsText(row),JSON.stringify(row.nearbyTextSnippets||[])].join(' ').toLowerCase()}a      function renderRows(){const q=$('search').value.trim().toLowerCase();const status=$('status').value;const promptOnly=$('promptOnly').checked;const filtered=data.rows.filter(row=>(!status||(row.cnsEvidenceStatus||'unbound')===status)&&(!promptOnly||row.linkedPromptCount)&&(!q||rowSearch(row).includes(q)));$('count').textContent=`${filtered.length} / ${data.rows.length}`;const rows=filtered.slice(0,1500);$('rows').innerHTML=rows.map(row=>{const firstPrompt=(row.linkedPrompts||[])[0];const cns=(row.nearbyCns||[]).slice(0,3).map(c=>`${c.name}`).join(', ');const flow=(row.linkedFlowGroups||[]).slice(0,2).map(g=>g.id).join(', ');return `<tr data-key="${esc(keyOf(row))}"><td><code>${esc(row.vaHex)}</code><br><small>${esc(row.confidence)}</small></td><td><code>${esc(row.opcodeHex)}</code></td><td>${chip(row.cnsEvidenceStatus,statusClass(row.cnsEvidenceStatus))}<br><small>${esc(short(row.classification,80))}</small></td><td>${firstPrompt?`<code>${esc(firstPrompt.id)}</code><br><small>${esc(short(firstPrompt.displayText,120))}</small>`:'-'}</td><td>${flow?esc(flow):'-'}</td><td>${cns?esc(cns):'-'}</td></tr>`}).join('')||'<tr><td colspan="6">No rows.</td></tr>';for(const tr of $('rows').querySelectorAll('tr[data-key]'))tr.addEventListener('click',()=>selectRow(tr.dataset.key));if(filtered.length>1500)$('rows').insertAdjacentHTML('beforeend','<tr><td colspan="6" class="muted">Showing first 1500 rows. Use filters to narrow the list.</td></tr>');highlightSelected()}z    function highlightSelected(){for(const tr of document.querySelectorAll('#rows tr[data-key]'))tr.classList.toggle('selected',tr.dataset.key===selectedKey)}u      function promptHtml(row){const prompts=row.linkedPrompts||[];if(!prompts.length)return '<p class="muted">No linked prompt.</p>';return `<div class="refs">${prompts.map(p=>`<div class="ref-row"><a href="story_prompts.html#${encodeURIComponent(p.id)}"><code>${esc(p.id)}</code></a> <a href="story_flow_review.html?prompt=${encodeURIComponent(p.id)}">flow</a><br><small>${esc(p.classification||'')} · wait ${esc(p.waitVaHex||'-')} · ${esc(p.flowEvidenceClass||'-')}</small><pre>${esc(p.displayText||'')}</pre></div>`).join('')}</div>`}u(      function groupsHtml(row){const groups=row.linkedFlowGroups||[];if(!groups.length)return '<p class="muted">No linked flow group.</p>';return `<div class="refs">${groups.map(g=>`<div class="ref-row"><a href="story_flow_review.html?group=${encodeURIComponent(g.id)}"><code>${esc(g.id)}</code></a> ${chip(g.stabilityClass||'-','blue')}<br><small>${esc(g.kind||'-')} · ${esc(g.key||'-')} · prompts ${esc(g.promptCount||'-')}</small><div>${esc(g.confidenceStatus||'')}</div><div class="muted">${esc(g.remainingRisk||'')}</div></div>`).join('')}</div>`}uI      function cnsHtml(row){const cns=row.nearbyCns||[];if(!cns.length)return '<p class="muted">No nearby CNS pointer.</p>';return `<div class="refs">${cns.map(c=>`<div class="ref-row"><code>${esc(c.name)}</code> ${chip(c.kind||'-')}<br><small>ref ${esc(c.refVaHex)} · distance ${esc(c.distance)}</small></div>`).join('')}</div>`}at      function routeHtml(row){const contexts=row.routeContexts||[];if(!contexts.length)return '<p class="muted">No route window context.</p>';return `<div class="refs">${contexts.map(c=>`<div class="ref-row"><code>${esc(c.map||'-')}</code> -> ${esc((c.targets||[]).join(', ')||'?')}<br><small>${esc(c.conditionVaHex)}..${esc(c.recordVaHex)}</small></div>`).join('')}</div>`}a0      function textSnippetHtml(row){const snippets=row.nearbyTextSnippets||[];if(!snippets.length)return '<p class="muted">No nearby decoded text snippets.</p>';return `<div class="refs">${snippets.map(s=>`<div class="ref-row"><code>${esc(s.vaHex)}</code><div>${esc(s.text)}</div></div>`).join('')}</div>`}a      function detailHtml(row){return `<dl class="kv"><dt>source</dt><dd>${esc(row.payload?.sourceDescription||'-')}</dd><dt>classification</dt><dd>${esc(row.classification||'-')}</dd><dt>CNS evidence</dt><dd>${chip(row.cnsEvidenceStatus,statusClass(row.cnsEvidenceStatus))}<div class="muted">${esc(row.cnsEvidenceNote||'')}</div></dd><dt>file offset</dt><dd><code>${esc(row.fileOffsetHex)}</code></dd><dt>handler</dt><dd><code>${esc(row.handlerVaHex)}</code></dd></dl><h2>Linked Prompts</h2>${promptHtml(row)}<h2>Flow Groups</h2>${groupsHtml(row)}<h2>Nearby CNS</h2>${cnsHtml(row)}<h2>Route Window Context</h2>${routeHtml(row)}<h2>Nearby Text Snippets</h2>${textSnippetHtml(row)}`}aD      function selectRow(key){selectedKey=key;const row=data.rows.find(r=>keyOf(r)===key);if(!row)return;highlightSelected();$('detailTitle').textContent=`${row.vaHex} ${row.opcodeHex}`;$('detail').classList.remove('muted');$('detail').innerHTML=detailHtml(row);history.replaceState(null,'',`?cmd=${encodeURIComponent(key)}`)}a      async function load(){const res=await fetch(DATA_URL,{cache:'no-store'});data=await res.json();const statuses=[...new Set(data.rows.map(r=>r.cnsEvidenceStatus||'unbound'))].sort();$('status').innerHTML='<option value="">all evidence</option>'+statuses.map(s=>`<option value="${esc(s)}">${esc(s)}</option>`).join('');$('search').addEventListener('input',renderRows);$('status').addEventListener('change',renderRows);$('promptOnly').addEventListener('change',renderRows);renderRows();const params=new URLSearchParams(location.search);const cmd=params.get('cmd');if(cmd){selectRow(cmd)}else{const first=data.rows.find(r=>r.linkedPromptCount)||data.rows[0];if(first)selectRow(keyOf(first));}}zv    load().catch(err=>{$('rows').innerHTML=`<tr><td colspan="6">Failed to load JSON: ${esc(err.message)}</td></tr>`});z  </script>z</body>z</html>)r   ru   r  r  r5   r-   r  )r  effect_rowsr   source_rowss       r!   	html_pager  a  s   K{{+,2 
S%567{4;;sSY{C[B\ ]S%89: ;;;s8}-. /;;s8}-. /		

 '' ;;89?R  4 
4  99 CCC 	C 	#	C
 	QC 	2C 	C 	rC 	VC 	HC 	BC 	@C 	IC 	yC 	AC  	l!C" 	t#C$ 	H%C& 	'C( 	)C* 	+C, 	i-C. 	!/C0 34;;w|?T3U2VVqr1C2 /w~/F.GwO3C4 9A[9\8]]de5C6 7w?W7X6YY`a7C8 8@Y8Z7[[bc9C: ;7C^;_:``gh;C< *$++djjI\A]lq6r*s)tt{|=C> 	?C@ 	OACB bggk*++KLCCD 	IECF {m56GCH 	GICJ 	RKCL 	MCN 	OCP 	<QCR 	0SCT 	7UCV 	IWCX 	}YCZ 	@[C\ 	h]C^ 	`_C` 	zaCb 	}cCd 	meCf 	ngCh 	[iCj 	ikCl 	omCn 	}oCp 	ZqCr 	EsCt 	AuCv 	w
wCx 	OyCz 	C{C| 	C}C~ 	C@ 	ACB 	CCD 	EC C Cr$   c                    |j                  dd       |dz  j                  t        j                  | dd      dz   d	       |d
z  j                  t	        |       d	       y )NT)parentsexist_okzevent_text_source_flow.jsonFrT   )r  indentr~  r)   r*   event_text_source_flow.html)mkdir
write_textr-   r  r  )r  out_dirs     r!   write_outputsr    sd    MM$M.,,88

7q9D@ 9  ,,8879KV]8^r$   c            	        t        j                         } | j                  dt        t        dz         | j                  dt        t
        dz         | j                  dt        t
        dz         | j                  dt        t
        d	z         | j                  d
t        t
               | j                         }t        |j                  j                         t        |j                  g       t        |j                  i       t        |j                  i             }t        ||j                         t!        d|j                  dz   d|d    d       y )Nz--exezHwanse2.exe)typer1   z--event-transitionszevent_transitions.jsonz--story-promptszstory_prompts.jsonz--story-flow-reviewzstory_flow_review.jsonz	--out-dirz wrote event text source flow -> r  z (r6  z
 commands))argparseArgumentParseradd_argumentr   ROOTOUT
parse_argsrX  rP   
read_bytesr2   r   r   r   r  r  print)parserargsr  s      r!   mainr    s-   $$&F
dD=4HI
-D#H`B`a
)cDX>XY
-D#H`B`a
$<D$(("-$$$b)$(("-	G '4<<(	*<<77
8 9N#$J	0r$   __main__)r    r   returnr6   )r0   r   )r'  )r:   r6   r;   r   r  r6   )rB   
list[dict]rC   r   r  
int | None)rB   r  r@   r   r  dict | None)rB   r  rC   r   r  r  )rP   r  rC   r   r  r  )rB   r  r    r  r  r  )rP   r  rB   r  r]   r   r  r   )ry   r  rz   r   r  r  )r  )rP   r  rB   r  r   dict[int, str]rC   r   r   r   r  r  )r   r  r  r  )r@   r   r   r  r  r  )r   r  r   r  r  dict[str, Any])r   rI  r  r6   )r   r6   r  r6   )r   rI  r   r  r  None)rP   r  rC   r   r   r   r  rI  )rP   r  rB   r  r   r  r   r  r   r  r  r  )r   r  r  r  )NNN)
rP   r  r   zlist[dict] | Noner   r  r   r  r  rI  )r    r6   r  r6   )r  rI  r  r6   )r  rI  r  r   r  r  )r  r  )@__doc__
__future__r   r  r  r-   rerM   collectionsr   pathlibr   typingr   probe_exe_scene_tablesr   r   r	   r
   __file__resolver  r  r  r  compilerq   r"   r'   r2   r<   rE   rG   rI   rQ   rU   rY   rb   r   r   r   r   r   r   r   r   r   r  r  r%  r)  rX  r\  re  rl  rp  rt  r{  r  r  r  r  r  __name__r   r$   r!   <module>r     s   R "    	     ^ ^ H~''*
Ul 1$n* 9$ hN .$ H& . "**q
r8%44	
"J.$
/dF70<	1	11 1 	1
 !1 1h( ,0!%%)	:	:(: : #	:
 
:z,;HG6#rRj 25 _, zF r$   