
    UHj%%                    L   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
 ddlmZmZ ddlmZmZmZ  e
e      j'                         j(                  d   Zed	z  Z ej.                  d
      ZddZddZddZdddZddZddZddZefddZ ddZ!e"dk(  r e!        yy)z@Scan decompressed CNS payloads for CP949 Korean text candidates.    )annotationsN)Counter)Path)decompress_cnsparse_image)
clean_textclassify_text	is_hangul   outzF^[\u3131-\u318e\uac00-\ud7a3A-Za-z0-9 !?.,:;_+\-/()[\]{}'\"~%&*<>|=]+$c                    d| dS )N0x08x )values    :/home/exedev/hwanse/tools/summarize_cns_text_candidates.pyhex32r      s    c{    c           
         t        |       dk\  rwt        j                  | dd d      }t        j                  | dd d      }d||z  dz  z   }d|cxk  rdk  r/n n,d|cxk  rdk  r!n nt        |       |k(  rd||t        |       dS t        |       dk\  rP| d   }| d   }d||z  dz  z   }d|cxk  rdk  r0n n-d|cxk  rdk  r"n nt        |       |k(  rd||dt        |       d	S 	 t        |       \  }}}}}||z  d
z   dz  dz  }||z  }d|cxk  rdk  rXn nUd|cxk  rdk  rJn nGt        |      |k\  r9dt        |      dz  z   }	d|||t        |      t	        t        |       |	|z         dS dddS # t
        $ r Y w xY w)N   r      little   tilemap)kindwidthheighttextScanStartr   )r   r   r   headerBytesr          i      image)r   r   r   bpppaletteColorsr   unknown)r   r   )lenint
from_bytesr   min	Exception)
decodedr   r   expected_mappalettepixelsr$   strideexpected_pixelspalette_ends
             r   classify_decoded_payloadr3      s   
7|qwq|X6!h756>A--uF 1c 1c'll6R%Z]^eZfgg
7|q
56>A--uF 1c 1c'll6R!  !$W .9'.B+vw3;#*a/ 6/uV!3t!3F8Vc'lQ..K !$W!$S\;3P!Q  22  s   %BE1 1	E=<E=c                
   | |   }|dv sd|cxk  rdk  ry ny|dk\  rW|dz   t        |       k  rF| |dz      dk7  r;| ||dz    }	 |j                  d      }t        |      st        j                  |      ryy# t        $ r Y yw xY w)	N)	   
      r!   ~   r      r   r   cp949)r'   decodeUnicodeDecodeErrorr
   PRINTABLE_REmatch)dataindexbytepairchars        r   valid_cp949_charrD   ?   s    ;D!!TT%9T%9 &:t|	CI-$uqy/Q2FE%!)$	;;w'D T?l006	 " 		s   A6 6	BBc           
     `   g }d}|t        |       k  r	| |   dk(  r|dz  }|}|t        |       k  r#t        | |      }|sn||z  }|t        |       k  r#||z
  dk\  r| || }	 |j                  d      }t	        |      }t        d |D              }	|	dk\  redt        |      cxk  rdk  rQn nNt        j                  |      r9|j                  ||z   t        ||z         t        |      ||	t        |      d	       t        |dz   |dz         }|t        |       k  r	|S # t        $ r d}Y w xY w)
Nr   r   r   r:    c              3  8   K   | ]  }t        |      sd   yw)r   N)r
   ).0rC   s     r   	<genexpr>z!scan_text_runs.<locals>.<genexpr>b   s     ETYt_qEs   r      )decodedOffsetdecodedOffsetHex
byteLengthtexthangulCountclassification)r'   rD   r;   r<   r   sumr=   r>   appendr   r	   max)
r?   base_offsetrowsr@   startstepblobr,   rN   hangul_counts
             r   scan_text_runsrZ   N   sW   DE
#d)
;!QJEc$i#D%0DTME	 c$i
 5=Ae$D++g. g&DETEEL!T)c) &&t,%05%8(-kE.A(B"%d) #/&3D&9  EAIuqy)? #d)
@ K% & s   #D D-,D-c                &   | j                   d ddd}	 t        | j                               }t        |      }|j                  t        |      |d   |j                  d      |j                  d      d       |j                  d	d      }||d  }||d	<   t        |      |d
<   t        ||      }|D ]'  }| j                   |d<   |d   |d<   t        |      |d<   ) t        |      |d<   ||fS # t        $ r}t	        |      |d<   |g fcY d }~S d }~ww xY w)Nr&   r   )namedecodedSizepayloadKindcandidateCounterrorr   r   r   )r]   r^   r   r   r   textScanBytesfiler^   r]   r_   )
r\   r   
read_bytesr+   strr3   updater'   getrZ   )	pathrowr,   excpayload
scan_start	scan_data
candidates	candidates	            r   	scan_filero   t   s0   		 	C !23 'w/GJJ7|vW%++h'	  _a0J
$I%Cy>C	:6J 0	 II	&#*6?	- #&w<	- 0  
OC
?)  3xGBws   C+ +	D4DDDc                   g }g }t        | j                  d            D ]2  }t        |      \  }}|j                  |       |j	                  |       4 |j                  d        t        d |D              }t        d |D              }dt        |       t        |      t        d |D              t        d |D              t        |      t        t        |j                                     t        t        |j                                     d	|D cg c]  }|j                  d
d      dkD  s| c}|d d dS c c}w )Nz*.cnsc                    | d   | d   | d   fS )NrP   rb   rK   r   )rh   s    r   <lambda>zbuild_summary.<locals>.<lambda>   s!    FO% r   )keyc              3  &   K   | ]	  }|d      yw)r^   Nr   rH   rh   s     r   rI   z build_summary.<locals>.<genexpr>   s     ACS/A   c              3  &   K   | ]	  }|d      yw)rP   Nr   ru   s     r   rI   z build_summary.<locals>.<genexpr>   s     GS3/0Grv   z7CP949 Korean string scan over decompressed CNS payloadsc              3  D   K   | ]  }|j                  d       d  yw)r]   Nr   rf   ru   s     r   rI   z build_summary.<locals>.<genexpr>   s     Yccggm6L6XYs     c              3  L   K   | ]  }|j                  d d      dkD  sd  yw)r_   r   r   Nry   ru   s     r   rI   z build_summary.<locals>.<genexpr>   s%     !Y@PRS8TWX8X!!Ys   $$a  This scan checks text-bearing regions of decompressed CNS payloads for plain CP949 text. Known image pixels and exact tilemap bodies are skipped to avoid pixel-noise false positives. A zero or very small result means story dialogue is probably not stored as simple null-delimited CP949 strings in these payloads; it may be encoded in another script format or generated through executable-side tables.r_   r   i  )scopesourcescannedFileCountdecodedFileCountcandidateFileCountr_   payloadKindCountsclassificationCounts
conclusionfilesWithCandidatesrm   )sortedglobro   rR   extendsortr   rd   r'   rQ   dictitemsrf   )	src_dirfilesrm   rg   file_rowfile_candidatespayload_countsclass_countsrh   s	            r   build_summaryr      s-   EJw||G,- +$-dO!/X/*+ OO O 
 A5AANGJGGLJg,JYUYY!!Yu!YYj/!&)=)=)?"@A $VL,>,>,@%A Bp
 05Y@PRS8TWX8XY #&!   Zs   D;.D;c                t   dj                  d | j                  d      xs g D              xs d}dj                  d | j                  d      xs g D              xs d}dj                  d	d
dddddddddt        j                  | d          dd| d    d| d    d| d    dddd| dd d!d| dd"d#dg      S )$NrF   c              3     K   | ]b  }d t        j                  |d          dt        j                  |d          d|j                  d      xs d d|j                  dd       d	 d y	w)
<tr><td>r\   	</td><td>r^   r]   -r_   r   
</td></tr>N)htmlescaperf   ru   s     r   rI   zhtml_page.<locals>.<genexpr>   s       	{{3v;'( ){{3}-./ 0ww}%,- .ww'+, -		s   A(A*r   zF<tr><td colspan="4">No CNS files contained CP949 candidates.</td></tr>c              3     K   | ]k  }d t        j                  |d          dt        j                  |d          dt        j                  |d          dt        j                  |d          d	 m y	w)
r   rP   r   rb   z</td><td><code>rL   z</code></td><td>rN   r   N)r   r   ru   s     r   rI   zhtml_page.<locals>.<genexpr>   s       	{{3/012 3{{3v;'( )[[%7!89: ;{{3v;'( )		s   A1A3rm   z1<tr><td colspan="4">No text candidates.</td></tr>
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>CNS Text Candidates</title>z  <style>body{font-family:system-ui,sans-serif;background:#101010;color:#eee;margin:24px}table{border-collapse:collapse;width:100%}td,th{border:1px solid #333;padding:6px 8px;vertical-align:top}th{background:#1d1d1d}code{color:#f5d76e}</style>z</head>z<body>z  <h1>CNS Text Candidates</h1>z  <p>r   z</p>z  <p>scanned: r}   z; decoded: r~   z; candidates: r_   z   <h2>Files With Candidates</h2>zd  <table><thead><tr><th>file</th><th>kind</th><th>decoded bytes</th><th>candidates</th></tr></thead>z	  <tbody>z</tbody></table>z  <h2>Candidates</h2>zX  <table><thead><tr><th>class</th><th>file</th><th>offset</th><th>text</th></tr></thead>z</body>z</html>)joinrf   r   r   )summary	file_rowscandidate_rowss      r   	html_pager      s>     ;;45;  R 
R  WW  ;;|,2  = 
=  99"P. 	~(
GL12348
!345[I[A\@]]kls  uE  mF  lG  GK  	L*n
I;./b
N##34
+  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cns_text_candidates.jsonFr   )ensure_asciiindentr   zutf-8)encodingcns_text_candidates.html)mkdir
write_textjsondumpsr   )r   out_dirs     r   write_outputsr      sd    MM$M.))55

7q9D@ 6  ))55i6HSZ5[r   c                 \   t        j                         } | j                  dt        t        dz         | j                  dt        t
               | j                         }t        |j                        }t        ||j                         t        d|j                  dz   d|d    d	       y )
Nz	--src-dirextract_fld)typedefaultz	--out-dirzwrote CNS text candidates -> r   z (r_   z candidates))argparseArgumentParseradd_argumentr   ROOTOUT
parse_argsr   r   r   r   print)parserargsr   s      r   mainr      s    $$&F
$}8LM
$<DDLL)G'4<<(	'<<44
5 6$%&l	4r   __main__)r   r(   returnrd   )r,   bytesr   r   )r?   r   r@   r(   r   r(   )r   )r?   r   rT   r(   r   z
list[dict])rg   r   r   ztuple[dict, list[dict]])r   r   r   r   )r   r   r   rd   )r   r   r   r   r   None)r   r   )#__doc__
__future__r   r   r   r   recollectionsr   pathlibr   
decode_cnsr   r    summarize_korean_text_candidatesr   r	   r
   __file__resolver   r   r   compiler=   r   r3   rD   rZ   ro   r   r   r   r   __name__r   r   r   <module>r      s    F "    	   2 Q Q H~''*
Ulrzzcd#3L#L@D)X 25 \ zF r   