
    UHj[K                       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mZ ddl	m
Z
  e
e      j                         j                  d   Zedz  Z ej                   d      Zd	Zg d
ddg dddg dddg ddddZddhZh dZddhZd-dZd.dZd/dZd0dZd0dZd1dZd2dZd3d Zd4d!Z	 	 	 	 	 	 	 	 d5d"Z d6d#Z!d7d8d$Z"d9d%Z#d:d&Z$d;d'Z%d;d(Z&efd<d)Z'd=d*Z(d>d+Z)e*d,k(  r e)        yy)?zLSummarize possible original save-point event hints from text/event evidence.    )annotationsN)Counter)Path   outz^map\d+_[0-9a-z]+\.cns$zPlayer memory says original saving was not available anywhere from the field menu. Saving happened through specific event interactions: village inns, field statues, and some HP-recovery NPCs.)   데이터 저장   데이터 로드   데이터가 없습니다z=original save/load UI text; not an event save-point by itself)keywordsdescription)u   여관u   숙박u	   하룻밤zinn or lodging dialogue context)   회복   치료   체력u   상처z\HP/recovery wording that may relate to recovery NPCs, but also has UI/battle false positives)   석상   신상u
   신의 산u   신의 사자zQstatue/shrine wording; exact statue words are stronger than location-only wording)save-uiinn-contextrecovery-contextstatue-shrine-contextr   r   >      파일 기록 실패   파일 읽기 실패r	   r   r
   zsystem-text-likezbattle-dialogue-likec                L    t        j                  | j                  d            S )Nutf-8encoding)jsonloads	read_text)paths    </home/exedev/hwanse/tools/summarize_save_point_candidates.py	load_jsonr!   0   s    ::dnngn677    c                6    |D cg c]	  }|| v s| c}S c c}w N )textr   keywords      r    matchesr(   4   s    #+?w$G???s   	c                z    t               }g }| D ])  }||v r|j                  |       |j                  |       + |S r$   )setaddappend)valuesseenresultvalues       r    uniquer1   8   sE    5DF D=e	
 Mr"   c                    | j                  d      xs g D cg c]&  }|j                  d      s|j                  dd      ( c}S c c}w )N	textLinesr&    get)blockrows     r    block_text_linesr9   C   s:    +099[+A+GR[C377SY?CGGFB[[[s
   AAc                   g }| j                  d      xs g D ]<  }t        j                  |      s|j                  t	        |      j
                         > | j                  d      xs g D ]I  }|j                  d      r%|j                  t	        |      j
                         9|j                  |       K t        |      S )NresourceNames	fieldMapsz.cns)r6   FIELD_MAP_REmatchr,   r   stemendswithr1   )r7   namesnames      r    block_field_mapsrC   G   s    E		/*0b *d#LLd)* 		+&," == LLd)LL	
 %=r"   c                    | j                  d      xs d}t        |      }|dk(  ry|dk(  r
|t        v ryy|dk(  r|d	hk  s|t        v ry
y|dk(  r|t        z  ryyy)Nclassificationr4   r   )system-ui-not-savepointzIDirect save/load words are in a system/menu block, not a map event proof.r   )weakz/Inn word appears in a system/battle-like block.)mediumz`Inn wording matches the player-memory save-point type, but no save opcode/event has been proven.r   r   )false-positive-likelyz3Recovery wording is status/battle/system-like here.)rG   z]Recovery wording exists in dialogue context, but it does not prove a recovery NPC save event.r   )rH   zFExact statue/shrine wording matches the player-memory save-point type.)weak-location-onlyzNOnly broad shrine/mountain wording is present; no exact statue text was found.)rG   zKeyword-only match.)r6   r*   SYSTEM_OR_BATTLE_CLASSESEXACT_STATUE_WORDS)r7   categoryr   matched_linesrE   keyword_sets         r    classify_event_candidaterP   T   s}    YY/06BNh-K9u= 55L{%%8*$:R(Rav**++eu(r"   c                t   g }| j                  d      xs g D ]  }t        |      }dj                  |      }t        j	                         D ]  \  }}t        ||d         }|s|D cg c]  t        fd|D              r }	}t        ||||	      \  }
}|j                  d|j                  d      |j                  d       d|j                  d	       |j                  d
      ||
|t        |      |j                  d      xs g |	d d |j                  d      xs |d d |d         |S c c}w )Nblocks
r   c              3  &   K   | ]  }|v  
 y wr$   r%   ).0r'   lines     r    	<genexpr>z)event_block_candidates.<locals>.<genexpr>t   s     C7w$Cs   event_dialogue_blocksblockId
startVaHexz..endVaHexrE   r;      
sampleText)sourcerY   rangeHexrE   rM   strengthr   r<   	resourcesmatchedLinesr]   reason)
r6   r9   joinCATEGORY_RULESitemsr(   anyrP   r,   rC   )rX   rowsr7   linesjoinedrM   rulehit_keywordsrV   rN   r`   rc   s           `   r    event_block_candidatesrm   h   sX   D&**84:  '5!,224 	NHd"64
+;<L "ClCC M 
  8xWdeHfKK1 99Y/$yy67r%))J:O9PQ"')),<"=$$(-e4"YY7=2 -cr 2#ii5Cs  	6 K)s   *D5c                   g }| j                  d      xs g D ]  }|j                  d      xs g D ]  }|j                  d      xs d}t        j                         D cg c]  \  }}t        ||d         r| }}}|sP|j	                  d|j                  d      |j                  d      |d	   d
||j                  d      |j                  d      dd	         |S c c}}w )Ntablesentriesr&   r4   r   text_tableskeytitler   rI   refVaHex	textVaHexzKThis is a named UI/item/action table entry, not an event save-point script.)	r^   table
tableTitlerM   r`   r&   rt   ru   rc   )r6   re   rf   r(   r,   )rq   findingsrv   entryr&   rM   rk   
categoriess           r    text_table_findingsr{      s    H*0b YYy)/R 	E99V$*D '5&:&:&<"Hd4j!12 J 
 OO'5)#ii0&qM3!IIj1"YY{3g
 
	* O%s   C 
c                :   g }| j                  d      xs g D ]{  }|j                  d      xs d}t        D cg c]	  }||v s| }}|s3|j                  ddd||j                  d      |j                  d      |j                  d	d
      |dd	       } |S c c}w )N
candidatesr&   r4   korean_text_candidatesr   rF   vaHexrE   refCountr   zYSystem file/save string evidence supports the save UI/path, not a map save-point trigger.)	r^   rM   r`   r&   r   rE   r   r   rc   )r6   SYSTEM_SAVE_WORDSr,   )r~   rx   r8   r&   wordrl   s         r    korean_text_findingsr      s    H%)),7=2 wwv$"):KddlKK.!1WWW%!gg&67
A.$q

 
	  O Ls   	BBc                   t        |       }t        |      }t        |      }t        d |D              }t        d |D              }|D cg c]  }|d   dk(  s| }	}|D cg c]1  }|d   dk(  r't	        |j                  d      xs g       t        z  r|3 }
}|D cg c]B  }|d   dk(  r8|j                  d      d	vr%t	        |j                  d      xs g       d
dhz  r|D }}|D cg c]  }|d   dk(  s| }}i dddt        d| j                  dd      dt        |      dt        t        |j                                     dt        t        |j                                     dt        |	      dt        |      dt        |
      dt        |      dt        |      dt        |      dddddd d!|d"||z   S c c}w c c}w c c}w c c}w )#Nc              3  &   K   | ]	  }|d      yw)rM   Nr%   rU   r8   s     r    rW   z build_summary.<locals>.<genexpr>   s     E3s:E   c              3  &   K   | ]	  }|d      yw)r`   Nr%   r   s     r    rW   z build_summary.<locals>.<genexpr>   s     D#c*oDr   rM   r   r   r   r   r`   >   rI   r   r   r   scopezXFirst-pass save-point candidate index from event dialogue blocks and Korean text tables.
userMemoryeventBlockCount
blockCountr   candidateEventBlockCountcandidateCountsstrengthCountsinnContextCountrecoveryNpcContextCountexactStatueMentionCountsaveUiTextBlockCounttextTableFalsePositiveCountsystemSaveTextFindingCountexactSavePointScriptProofF#originalSavePointRuntimeImplemented
conclusionu  This pass separates original save/load UI text from possible map-event save-point contexts. The only direct save text found in event dialogue blocks is system/menu text, while inn wording appears in several dialogue contexts. No exact 석상/신상 text and no proven HP-recovery NPC save event were found yet, so browser 임시 저장 remains a debug path and original save-point behavior is still unimplemented.r}   nonSavePointTextFindings)rm   r{   r   r   r*   r6   rL   USER_MEMORYlendictsortedrf   )rX   r~   rq   r}   table_findingssystem_findingscandidate_countsstrength_countsr8   inn_candidatesexact_statue_candidatesrecovery_candidatessave_ui_candidatess                r    build_summaryr      sw   
 ((=>J(5N*+ABOE*EEDDDO%/Tc3z?m3ScTNT z?55
#)r*-?? 	  z?00GGJ'@@
#)r*h-AA	 	  *4T#s:)7S#TTkk 	044\1E 	#C
O	
 	4'7'='='? @A 	$vo&;&;&=>? 	3~. 	"3':#; 	"3'>#? 	$6 7 	&s>': 	%c/&: 	$U 	.u 	&!, 	j-. 	#N_$D/  U Us%   
G
G
"6GAG+G9Gc                8    t        |       j                  dd      S )N|z\|)strreplace)r&   s    r    escape_cellr      s    t9S%((r"   c                ~    dj                  | j                  d      xs | j                  d      xs g d |       xs dS )Nz / rb   r]   -)rd   r6   )r8   limits     r    sample_textr      s;    ::sww~.M#'',2GM2vPUVW^[^^r"   c                    ddddd}dddddd}|j                  | j                  d      d	      |j                  | j                  d
      d	      | j                  d      xs dfS )Nr   r         )r   r   r   r      )rH   rG   rJ   rI   rF   rM   	   r`   rY   r4   r5   )r8   category_orderstrength_orders      r    candidate_sort_keyr      s|    !"	N !"#$N 	377:.2377:.2	 b r"   c                8   g }t        | j                  d      xs g t              D ]  }|j                  |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      xs g |j                  d	      xs g |j                  d
      xs g |j                  d      xs g |j                  d      xs g |j                  d      xs dd        | j                  d      | j                  d      t	        |      | j                  dd      | j                  dd      | j                  dd      | j                  dd      | j                  d      du | j                  d      du |d
S )Nr}   rr   r^   rY   r_   rM   r`   r   r<   ra   rb   r]   rc   r4   )r^   rY   r_   rM   r`   r   r<   ra   rb   r]   rc   r   r   r   r   r   r   r   r   Tr   )
r   r   candidateCountr   r   r   r   r   r   r}   )r   r6   r   r,   r   )summaryr}   r8   s      r    runtime_candidatesr     sq   Jgkk,/52;MN ggh'wwy)
+
+
+
+1r-3-3GGN39r'',/52ggh'-2
 	 W%kk,/j/";;'8!<#*;;/H!#L#*;;/H!#L ',BA F%,[[1L%MQU%U/6{{;`/aei/i  r"   c                   dd| d   dd| d    d| d    d| d	    d
| d    d| d    d| d    d| d    d| d    ddd| d   dddddg}t        | j                  d      xs g t              D ]  }|j                  d|j                  d       d|j                  d       d|j                  d        dt	        d!j                  |j                  d"      xs g              dt	        d!j                  |j                  d#      xs g       xs d$       dt	        t        |             dt	        |j                  d%      xs d$       d&        | j                  d      s|j                  d'       |j                  g d(       | j                  d)      xs g D ]  }|j                  d*      xs( |j                  d+      xs |j                  d,      xs d$}|j                  d,      r|j                  d,       d-| }|j                  d.|j                  d/       d|j                  d       d|j                  d        dt	        |       dt	        |j                  d%      xs d$       d&        | j                  d)      s|j                  d0       |j                  g d1       d2j                  |      d2z   S )3Nz# Save Point Candidatesr4   r   z!- event dialogue blocks scanned: r   z- candidate event rows: r   z- inn contexts: r   z- recovery NPC contexts: r   z - exact statue/shrine mentions: r   z- save UI text blocks: r   z!- exact save-point script proof: r   z+- original save-point runtime implemented: r   z## Player Memoryr   z## Event CandidateszO| block | category | strength | keywords | field maps | matched text | reason |z+| --- | --- | --- | --- | --- | --- | --- |r}   r   z| `rY   z` | rM   z | r`   , r   r<   r   rc   z |z| - | - | - | - | - | - | - |)r4   z## Non-Save-Point Text Findingsr4   z6| source | category | strength | text/table | reason |z| --- | --- | --- | --- | --- |r   r&   rw   rv   : z| r^   z| - | - | - | - | - |)r4   z## Next Workr4   ze- Trace the event/object VM opcode that opens original save UI from inn/statue/recovery interactions.z- Find exact map/object coordinates for any candidate save-point NPC or statue before enabling original save behavior in `/web/index.html`.ua   - Keep browser-local `임시 저장/임시 불러오기` separate from original save-point rules.rS   )r   r6   r   r,   r   rd   r   extend)r   ri   r8   labels       r    markdownr   &  s   !


+G4E,F+GH
"7+E#F"GH
7#4567
#G,E$F#GH
*73L+M*NO
!'*@"A!BC
+G4O,P+QR
5g>c6d5ef



Y5+E. gkk,/52;MN 
#'')$%T#''**=)>c#''*BUAVVY499SWWZ%8%>B?@A499SWW[%9%?R@GCHI;s+,-SSWWX=N=URU1V0WWY[	

 ;;|$45	LL   {{56<" 
S377<#8SCGGG<LSPS777www'(5'2E"#3swwz':&;3swwz?R>SSV5!"#k#''(2C2Js&K%LBP	
	
 ;;12,-	LL   99Ud""r"   c                $   g }t        | j                  d      xs g t              D ][  }|j                  dt	        j
                  t        |j                  d                   dt	        j
                  t        |j                  d                   dt	        j
                  t        |j                  d                   dt	        j
                  d	j                  |j                  d
      xs g              dt	        j
                  d	j                  |j                  d      xs g       xs d       dt	        j
                  t        |             dt	        j
                  |j                  d      xs d       d       ^ g }| j                  d      xs g D ]I  }|j                  d      xs( |j                  d      xs |j                  d      xs d}|j                  d      r|j                  d       d| }|j                  dt	        j
                  t        |j                  d                   dt	        j
                  t        |j                  d                   dt	        j
                  t        |j                  d                   dt	        j
                  t        |             dt	        j
                  |j                  d      xs d       d       L dj                  dddddddddd d!t	        j
                  | d"          d#d!t	        j
                  | d$          d#d%| d&    d'| d(    d)| d*    d+| d,    d-| d.    d/d0d1d2d3j                  |      xs d4 d5d6d7d2d3j                  |      xs d8 d5d9d:d3g      S );Nr}   r   z<tr><td><code>rY   z</code></td><td>rM   z	</td><td>r`   r   r   r<   r   rc   z
</td></tr>r   r&   rw   rv   r   z<tr><td>r^   rS   z<!doctype html>z<html lang="en">z<head>z  <meta charset="utf-8">zF  <meta name="viewport" content="width=device-width, initial-scale=1">z&  <title>Save Point Candidates</title>a4    <style>body{font-family:system-ui,sans-serif;background:#101010;color:#eee;margin:24px}table{border-collapse:collapse;width:100%;margin:16px 0 28px}td,th{border:1px solid #333;padding:6px 8px;vertical-align:top}th{background:#1d1d1d}code{color:#f5d76e}.badge{display:inline-block;margin-right:12px}</style>z</head>z<body>z   <h1>Save Point Candidates</h1>z  <p>r   z</p>r   z'  <p><span class="badge">inn contexts: r   z.</span><span class="badge">recovery contexts: r   z2</span><span class="badge">exact statue mentions: r   z+</span><span class="badge">save UI blocks: r   z)</span><span class="badge">script proof: r   z</span></p>z  <h2>Event Candidates</h2>z  <table><thead><tr><th>block</th><th>category</th><th>strength</th><th>keywords</th><th>field maps</th><th>matched text</th><th>reason</th></tr></thead>z	  <tbody>r4   z,<tr><td colspan="7">No candidates.</td></tr>z</tbody></table>z'  <h2>Non-Save-Point Text Findings</h2>zt  <table><thead><tr><th>source</th><th>category</th><th>strength</th><th>text/table</th><th>reason</th></tr></thead>z*<tr><td colspan="5">No findings.</td></tr>z</body>z</html>)	r   r6   r   r,   htmlescaper   rd   r   )r   candidate_rowsr8   non_save_rowsr   s        r    	html_pager   c  s   Ngkk,/52;MN 
S);%<=> ?;;s377:#6789 :;;s377:#6789 :;;tyy)<)BCDE F;;tyy)=)CDKLM N;;{3/01 2;;swwx07C89 :
	

 M{{56<" 
S377<#8SCGGG<LSPS777www'(5'2E;;s3778#4567 8;;s377:#6789 :;;s377:#6789 :;;s5z*+ ,;;swwx07C89 :	
	
 99"P0 	*
GL12348
GL12348	//67H/I.J K44;<U4V3W X88?@Y8Z7[ \1189O1P0Q R//67R/S.T U	 	& 	d
BGGN+_/_``pq1~
BGGM*\.\]]mn
9  r"   c                <   |j                  dd       |dz  j                  t        j                  | dd      dz   d	       |d
z  j                  t	        |       d	       |dz  j                  dt        j                  t        |       dd      z   dz   d	       y )NT)parentsexist_okzsave_point_candidates.jsonFr   )ensure_asciiindentrS   r   r   zsave_point_candidates.htmlz save_point_candidates_runtime.jsz&window.HWANSE_SAVE_POINT_CANDIDATES = ),:)r   
separatorsz;
)mkdir
write_textr   dumpsr   r   )r   out_dirs     r    write_outputsr     s    MM$M.++77

7q9D@ 8  ++77	'8JU\7]11==0
**'0uQ[
\	]
	 	 > r"   c                 H   t        j                  t              } | j                  dt        t
        dz         | j                  dt        t
        dz         | j                  dt        t
        dz         | j                  d	t        t
               | j                         S )
N)r   z--event-dialoguezevent_dialogue_blocks.json)typedefaultz--korean-textzkorean_text_candidates.jsonz--text-tablesztext_tables.jsonz	--out-dir)argparseArgumentParser__doc__add_argumentr   OUT
parse_args)parsers    r    r   r     s    $$9F
*sEa?ab
dCB_<_`
dCBT<TU
$<r"   c                     t               } t        t        | j                        t        | j                        t        | j
                              }t        || j                         y r$   )r   r   r!   event_dialoguekorean_textrq   r   r   )argsr   s     r    mainr     sM    <D$%%&$""#$""#G
 '4<<(r"   __main__)r   r   returnr   )r&   r   r   	list[str]r   r   )r-   r   r   r   )r7   r   r   r   )
r7   r   rM   r   r   r   rN   r   r   ztuple[str, str])rX   r   r   
list[dict])rq   r   r   r   )r~   r   r   r   )rX   r   r~   r   rq   r   r   r   )r&   r   r   r   )   )r8   r   r   intr   r   )r8   r   r   ztuple[int, str, str])r   r   r   r   )r   r   r   r   )r   r   r   r   r   None)r   zargparse.Namespace)r   r   )+r   
__future__r   r   r   r   recollectionsr   pathlibr   __file__resolver   ROOTr   compiler=   r   re   rL   r   rK   r!   r(   r1   r9   rC   rP   rm   r{   r   r   r   r   r   r   r   r   r   r   r   __name__r%   r"   r    <module>r      sb   R "    	   H~''*
Ulrzz45!  ZV
 68
 =u
 Hj& )  J .0FG 8@\
)(@4*11 1 1 
	1h)_*<:#z9x 25 ) zF r"   