§
    #–¿jo#  ã                   ó  — d 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 g d¢Zg d¢Z ej        d	¦  «        Zg d
¢Zg  ej        dej        ¦  «        ‘ ej        dej        ¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        dej        ¦  «        ‘ ej        dej        ¦  «        ‘ ej        dej        ¦  «        ‘ ej        dej        ¦  «        ‘ ej        dej        ¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        dej        ¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        d¦  «        ‘ ej        d ¦  «        ‘ ej        d!¦  «        ‘ ej        d"ej        ¦  «        ‘ ej        d#¦  «        ‘ ej        d$¦  «        ‘ ej        d%¦  «        ‘ ej        d&¦  «        ‘ ej        d'¦  «        ‘ ej        d(¦  «        ‘ ej        d)¦  «        ‘Zd*„ Zd+„ Zd,„ Zd-„ Zd.„ Zd/„ Zd0„ Zd1„ Zd2„ ZdS )3zß
Unit test suite for FreeExile 9-Language Novel Localization Integrity.
Validates 100% adherence to canonical nomenclature, 216 chapter files,
0 residual Vietnamese characters in non-VI editions, and 0 vulgarity/anomalies.
é    N)ÚPath)ÚCHAPTER_TITLES)ÚCANONICAL_SECTION_HEADINGS)ÚENTITY_DICTIONARY)	ÚviÚenÚzhÚjaÚkoÚthÚdeÚruÚes)r   r	   r
   r   r   r   r   r   u“   [ÄƒÃ¢Ä‘ÃªÃ´Æ¡Æ°Ä‚Ã‚Ä�ÃŠÃ”Æ Æ¯áº±áº§á»�á»“á»�á»«áº³áº©áº»á»ƒá»‰á»�á»•á»Ÿá»§á»­á»·áºµáº«áº½á»…Ä©Ãµá»—á»¡Å©á»¯á»¹áº¡áº·áº­áº¹á»‡á»‹á»�á»™á»£á»¥á»±á»µ])zCon CotzNuoc DuczHac ThizHoang Cot ThozHung Sa CotzBang LoizLai Bo Thi Langz	Dai DoanhzCo ThizKim Van NhuczVu Hoa Shinhzfloorable sandwich bowlzMenstrual HatezSEXUALITY RISEu   æŒ‰æ‘©é»‘äººzKIM LOAN ELECTRICITYzTWO BINH CHANGEz	Chan Thuyz
Chan Thienz	Thanh LaczHai Monz	Trong Daou
   Qing Láº¡czJiang KyzNIVELA EL JIANG KYõ   ê³ ìœ„ ê°�ê·¤õ   é«˜ä½�ã�®ã�¿ã�‹ã‚“ÚmenstruÚ
monatsblutu   à¸›à¸£à¸°à¸ˆà¸³à¹€à¸”à¸·à¸­à¸™u   ç»�è¡€u   ç»�æœŸu   çµŒè¡€u   çµŒæœŸu   ìƒ�ë¦¬u	   ìƒ�ë¦¬í˜ˆz\bperiods?\bu   \bper[iÃ­]odos?\bz\bperiode[n]?\bu   \bÐ¿ÐµÑ€Ð¸Ð¾Ð´\w*zjiang kyr   r   zcapital of deathu	   æ­»åˆ‘æœŸu   æ­»åˆ‘æ™‚ä»£u   ì‚¬í˜•ì‹œëŒ€u   ì‚¬í˜•ìˆ˜\s*ê°�ì˜¥\s*ê¸°ê°„u<   à¸Šà¹ˆà¸§à¸‡à¸ˆà¸³à¸„à¸¸à¸�à¸›à¸£à¸°à¸«à¸²à¸£à¸Šà¸µà¸§à¸´à¸•u-   à¸Šà¹ˆà¸§à¸‡à¹�à¸«à¹ˆà¸‡à¸„à¸§à¸²à¸¡à¸•à¸²à¸¢zZeit des Todesu   å‰‘æ´¾å�²è¯—çº§u   å£®å¤§ã�ªæ™‚ä»£u   ê²€íŒŒì�˜ ì„œì‚¬ì‹œu!   à¸¢à¸¸à¸„à¸¡à¸«à¸²à¸�à¸²à¸žà¸¢à¹Œu   ã‚¼ãƒ³ãƒˆ\d*u   ä¸ƒå¹´å‰�ä¸ƒå¹´å‰�z$vor sieben Jahren.*vor sieben Jahrenc                  óÂ   — t           D ]V} t          dd¦  «        D ]C}d| › d|d›d�}t          j        |¦  «        }t          |¦  «        dk    sJ d|› d| › �¦   «         ‚ŒDŒWd	S )
zKVerify that all 24 chapters across 9 canonical languages exist (216 files).é   é   únovels/locales/ú/act_*/chuong_Ú03dú_*.mdúMissing chapter z for language N)Ú	LANGUAGESÚrangeÚglobÚlen)ÚlangÚchÚpatternÚmatchess       úEC:\Projects\FreeExile\tests\unit\test_novel_localization_integrity.pyÚ)test_exactly_216_localized_chapters_existr%   B   s›   € åð Rð RˆÝ˜˜2‘,”,ð 	Rð 	RˆBØI¨ÐIÐI¸BÐIÐIÐIÐIˆGÝ”i Ñ(Ô(ˆGÝ�w‘<”< 1Ò$Ð$Ð$Ð&Q¸Ð&QÐ&QÈ4Ð&QÐ&QÑ$Ô$Ð$Ð$ð	RðRð Ró    c            	      óT  — dddddœ} t          dd¦  «        D �]}t          D �]}t          j        d|› d	|d
›d�¦  «        }|sJ d|› d|› �¦   «         ‚t          |d         ¦  «                             d¬¦  «        }|                     ¦   «         d                              ¦   «         }t          |         |         }|dk    rd|› d|› �|v sJ ‚Œ¬|dv rd|› d|› �|k    sJ ‚Œ¿|dk    rd|› d|› �|k    sJ ‚ŒÔ|dk    rd|› d|› �|k    sJ ‚Œé| |         }d|› d|› d|› �|k    sJ ‚�Œ�ŒdS )zNVerify that every chapter title level-1 heading matches the canonical catalog.ÚCHAPTERÚKAPITELu
   Ð“Ð›Ð�Ð’Ð�u	   CAPÃ�TULO)r   r   r   r   r   r   r   r   r   r   r   z for r   úutf-8©Úencodingr   u	   CHÆ¯Æ NG z: )r	   r
   u   # ç¬¬u   ç« ï¼šr   u   # ì œu   ìž¥: r   u   # à¸šà¸—à¸—à¸µà¹ˆ z# ú N)r   r   r   r   Ú	read_textÚ
splitlinesÚstripr   )Ú
prefix_mapr!   r    ÚfilesÚcontentÚ
first_lineÚtitleÚprefixs           r$   Ú#test_chapter_titles_match_canonicalr7   J   sá  € ð ØØØð	ð €Jõ �A�r‰lŒlð Añ AˆÝð 	Añ 	AˆDÝ”IÐQ°ÐQÐQÀBÐQÐQÐQÐQÑRÔRˆEØÐ<Ð<Ð<¨RÐ<Ð<°dÐ<Ð<Ñ<Ô<�5Ý˜5 œ8‘n”n×.Ò.¸Ð.Ñ@Ô@ˆGØ ×+Ò+Ñ-Ô-¨aÔ0×6Ò6Ñ8Ô8ˆJÝ" 2Ô& tÔ,ˆEà�tŠ|ˆ|Ø0 2Ð0Ð0¨Ð0Ð0°JÐ>Ð>Ð>Ð>Ð>Ø˜Ð%Ð%Ø0˜rÐ0Ð0¨Ð0Ð0°JÒ>Ð>Ð>Ð>Ð>Ø˜’�Ø/˜rÐ/Ð/¨Ð/Ð/°:Ò=Ð=Ð=Ð=Ð=Ø˜’�Ø9¨BÐ9Ð9°%Ð9Ð9¸ZÒGÐGÐGÐGÐGà# DÔ)�Ø2˜FÐ2Ð2 RÐ2Ð2¨5Ð2Ð2°jÒ@Ð@Ð@Ð@Ñ@ñ#	AðAð Ar&   c                  ó  — t          dd¦  «        D �]m} t          j        d| d›d�¦  «        }t          |d         ¦  «                             d¬¦  «        }d	„ |                     ¦   «         D ¦   «         }t
          D �]}t          j        d
|› d| d›d�¦  «        }t          |d         ¦  «                             d¬¦  «        }d„ |                     ¦   «         D ¦   «         }t          |¦  «        t          |¦  «        k    s0J d| › d|› dt          |¦  «        › dt          |¦  «        › �¦   «         ‚t          |¦  «        D ];\  }}	t          ||                  |         }
|	|
k    sJ d| › d|› d|	› d|
› d�	¦   «         ‚Œ<�Œ�ŒodS )zRVerify that every section heading in all 216 files matches the canonical headings.r   r   znovels/locales/vi/act_*/chuong_r   r   r   r*   r+   c                 ó„   — g | ]=}|                      ¦   «                              d ¦  «        ¯)|                      ¦   «         ‘Œ>S ©z### ©r0   Ú
startswith©Ú.0Úls     r$   ú
<listcomp>zAtest_all_113_section_headings_match_canonical.<locals>.<listcomp>k   s<   € ÐbÐbÐb QÀQÇWÂWÁYÄY×EYÒEYÐZ`ÑEaÔEaÐb�q—w’w‘y”yÐbÐbÐbr&   r   r   c                 ó„   — g | ]=}|                      ¦   «                              d ¦  «        ¯)|                      ¦   «         ‘Œ>S r:   r;   r=   s     r$   r@   zAtest_all_113_section_headings_match_canonical.<locals>.<listcomp>p   s<   € ÐjÐjÐj¨1ÈQÏWÊWÉYÌY×MaÒMaÐbhÑMiÔMiÐj˜QŸWšW™YœYÐjÐjÐjr&   zChapter z (z) has z headings, expected z) heading mismatch: 'z' != 'ú'N)	r   r   r   r.   r/   ÚNON_VI_LANGUAGESr   Ú	enumerater   )r!   Úvi_filesÚ
vi_contentÚvi_headingsr    Ú
lang_filesÚlang_contentÚlang_headingsÚidxÚhÚexpecteds              r$   Ú-test_all_113_section_headings_match_canonicalrN   f   sÍ  € å�A�r‰lŒlð ñ ˆÝ”9ÐL¸rÐLÐLÐLÐLÑMÔMˆÝ˜( 1œ+Ñ&Ô&×0Ò0¸'Ð0ÑBÔBˆ
ØbÐb¨*×*?Ò*?Ñ*AÔ*AÐbÑbÔbˆå$ð 	ñ 	ˆDÝœÐ#V°TÐ#VÐ#VÈÐ#VÐ#VÐ#VÐ#VÑWÔWˆJÝ 
¨1¤Ñ.Ô.×8Ò8À'Ð8ÑJÔJˆLØjÐj°×0GÒ0GÑ0IÔ0IÐjÑjÔjˆMå�}Ñ%Ô%­¨[Ñ)9Ô)9Ò9Ð9Ð9Øg˜2ÐgÐg ÐgÐg­S°Ñ-?Ô-?ÐgÐgÕUXÐYdÑUeÔUeÐgÐgñ :Ô9Ð9õ $ MÑ2Ô2ð ð ‘��QÝ5°kÀ#Ô6FÔGÈÔM�Ø˜H’}�}�}ØT˜rÐTÐT TÐTÐTÀÐTÐTÈÐTÐTÐTñ %”}�}�}ññ	ðð r&   c                  ó8  — g } t           D ]€}t          j        d|› d�¦  «        D ]e}t          |¦  «                             d¬¦  «        }t                               |¦  «        }|r$|                      |t          |¦  «        f¦  «         ŒfŒ�| rJ d| › �¦   «         ‚dS )zIVerify that zero pure Vietnamese characters remain in any non-VI edition.r   ú/act_*/*.mdr*   r+   z&Found residual Vietnamese diacritics: N)rC   r   r   r.   ÚPURE_VI_DIACRITICSÚfindallÚappendÚset)Ú
violationsr    Úfpathr3   r#   s        r$   Ú.test_zero_pure_vietnamese_diacritics_in_non_virW   |   s»   € à€JÝ ð 9ð 9ˆÝ”YÐB°ÐBÐBÐBÑCÔCð 	9ð 	9ˆEÝ˜5‘k”k×+Ò+°WÐ+Ñ=Ô=ˆGÝ(×0Ò0°Ñ9Ô9ˆGØð 9Ø×!Ò! 5­#¨g©,¬,Ð"7Ñ8Ô8Ð8øð		9ð ÐPÐPÐPÀJÐPÐPÑPÔPˆ>ÐPÐPr&   c                  ó  — g } t           D ]e}t          j        d|› d�¦  «        D ]J}t          |¦  «                             d¬¦  «        }t          D ]}||v r|                      ||f¦  «         ŒŒKŒf| rJ d| › �¦   «         ‚dS )zNVerify that no corrupted tokens or vulgar machine-translation artifacts exist.r   rP   r*   r+   z"Found anomalous or vulgar tokens: N)rC   r   r   r.   ÚANOMALOUS_STRINGSrS   )Úfoundr    rV   r3   Útokens        r$   Ú%test_zero_anomalous_or_vulgar_stringsr\   ˆ   s¶   € à€EÝ ð 1ð 1ˆÝ”YÐB°ÐBÐBÐBÑCÔCð 	1ð 	1ˆEÝ˜5‘k”k×+Ò+°WÐ+Ñ=Ô=ˆGÝ*ð 1ð 1�Ø˜GÐ#Ð#Ø—L’L %¨ Ñ0Ô0Ð0øð1ð	1ð ÐBÐBÐB¸5ÐBÐBÑBÔBˆ9ÐBÐBr&   c                  ó4  — g } t           D ]~}t          j        d|› d�¦  «        D ]c}t          |¦  «                             d¬¦  «        }t          D ]6}|                     |¦  «        }|r|                      ||j        |f¦  «         Œ7ŒdŒ| rJ d| › �¦   «         ‚dS )u\   Verify that zero menstrual or inappropriate period/era mistranslations of 'kinh ká»³' exist.r   rP   r*   r+   z8Found forbidden menstrual/period mistranslation tokens: N)rC   r   r   r.   ÚFORBIDDEN_KINH_KY_PATTERNSrR   rS   r"   )rZ   r    rV   r3   Úpatr#   s         r$   Ú1test_zero_menstrual_or_inappropriate_period_termsr`   ”   sÓ   € à€EÝ ð @ð @ˆÝ”YÐB°ÐBÐBÐBÑCÔCð 	@ð 	@ˆEÝ˜5‘k”k×+Ò+°WÐ+Ñ=Ô=ˆGÝ1ð @ð @�ØŸ+š+ gÑ.Ô.�Øð @Ø—L’L %¨¬°gÐ!>Ñ?Ô?Ð?øð@ð	@ð ÐXÐXÐXÐQVÐXÐXÑXÔXˆ9ÐXÐXr&   c                  óæ   — g } t           D ]W}t          j        d|› d�¦  «        D ]<}t          |¦  «                             ¦   «         }d|v r|                      |¦  «         Œ=ŒX| rJ d| › �¦   «         ‚dS )z?Verify that all 216 chapter files strictly use LF line endings.r   rP   s   
zFiles with CRLF endings: N)r   r   r   Ú
read_bytesrS   )Ú
crlf_filesr    rV   Údatas       r$   Ú'test_no_crlf_line_endings_in_any_localere   ¡   s™   € à€JÝð )ð )ˆÝ”YÐB°ÐBÐBÐBÑCÔCð 	)ð 	)ˆEÝ˜‘;”;×)Ò)Ñ+Ô+ˆDØ˜$ˆˆØ×!Ò! %Ñ(Ô(Ð(øð	)ð
 ÐCÐCÐC°zÐCÐCÑCÔCˆ>ÐCÐCr&   c                  ó  — t          t          ¦  «        dk    sJ ‚t          t          ¦  «        dk    sJ ‚t          t          ¦  «        dk    sJ ‚d„ t          D ¦   «         } | t	          | d¬¦  «        k    s
J d¦   «         ‚dS )	z'Verify catalog imports and size limits.é   éq   éd   c                 ó8   — g | ]}t          |d          ¦  «        ‘ŒS )r   )r   )r>   Úes     r$   r@   z6test_catalogs_and_entity_integrity.<locals>.<listcomp>³   s"   € Ð4Ð4Ð4˜Q�s�1�Q”4‰yŒyÐ4Ð4Ð4r&   T)Úreversez1ENTITY_DICTIONARY not sorted descending by lengthN)r   r   r   r   Úsorted)Úlengthss    r$   Ú"test_catalogs_and_entity_integrityro   ¬   s’   € å�~ÑÔ "Ò$Ð$Ð$Ð$ÝÕ)Ñ*Ô*¨cÒ1Ð1Ð1Ð1ÝÕ Ñ!Ô! SÒ(Ð(Ð(Ð(ð 5Ð4Õ"3Ð4Ñ4Ô4€GØ•f˜W¨dÐ3Ñ3Ô3Ò3Ð3Ð3Ð5hÑ3Ô3Ð3Ð3Ð3r&   c                  óÊ   — g d¢} | D ][\  }}}t          j         d|› d|› �¦  «        D ]:}t          |¦  «                             d¬¦  «        }||vsJ d|› d|› d�¦   «         ‚Œ;Œ\d	S )
zPVerify that audited first-person slips in third-person narration are eradicated.))r   zchuong_001_*.mdztearing through my dry lungs)r   zchuong_009_*.mdz&receded to my knees, then to my ankles)r   úchuong_010_*.mdz My blade was made of Crude Flint)r   rq   zIn just one slash, I cut)r   zchuong_015_*.mdzcorners of my dry, cracked lips)r   rq   u[   à¹ƒà¸šà¸¡à¸µà¸”à¸‚à¸­à¸‡à¸‰à¸±à¸™à¸—à¸³à¸ˆà¸²à¸� à¸«à¸´à¸™à¹€à¸«à¸¥à¹‡à¸�à¹„à¸Ÿà¸«à¸¢à¸²à¸š)r   rq   u3   à¸‰à¸±à¸™à¸•à¸±à¸”à¹‚à¸‹à¹ˆà¹€à¸«à¸¥à¹‡à¸�à¸«à¸™à¸²)r
   zchuong_022_*.mdu?   ã‚‚ã�—ç§�ã�Ÿã�¡ã�Œã��ã�®è…�ã�£ã�ŸçŽ‹åº§ã‚’ç ´å£Šã�—ã�ªã�‘ã‚Œã�°r   z/act_*/r*   r+   zFound POV slip in z: 'rB   N)r   r   r.   )Úchecksr    Úglob_patÚforbidden_strrV   r3   s         r$   Ú test_zero_pov_slips_in_narrationru   ¶   s¸   € ð	ð 	ð 	€Fð *0ð að aÑ%ˆˆh˜Ý”YÐH°ÐHÐH¸hÐHÐHÑIÔIð 	að 	aˆEÝ˜5‘k”k×+Ò+°WÐ+Ñ=Ô=ˆGØ ¨Ð/Ð/Ð/Ð1`ÀeÐ1`Ð1`ÐP]Ð1`Ð1`Ð1`Ñ/Ô/Ð/Ð/ð	aðað ar&   )Ú__doc__ÚosÚrer   ÚpytestÚpathlibr   Ú'tools.localization.novel_titles_catalogr   Ú)tools.localization.novel_headings_catalogr   Ú)tools.localization.novel_entities_catalogr   r   rC   ÚcompilerQ   rY   Ú
IGNORECASEr^   r%   r7   rN   rW   r\   r`   re   ro   ru   © r&   r$   ú<module>r�      sQ  ððð ð 
€	€	€	Ø 	€	€	€	Ø €€€Ø €€€Ø Ð Ð Ð Ð Ð à BÐ BÐ BÐ BÐ BÐ BØ PÐ PÐ PÐ PÐ PÐ PØ GÐ GÐ GÐ GÐ GÐ GàBÐBÐB€	ØCÐCÐCÐ à�R”Zð  !wñ  xô  xÐ ðð ð Ð ð Ø€B„Jˆz˜2œ=Ñ)Ô)ð à€B„Jˆ}˜bœmÑ,Ô,ð ð €B„JÐ0Ñ1Ô1ð ð €B„JˆyÑÔð	 ð
 €B„JˆyÑÔð ð €B„JˆyÑÔð ð €B„JˆyÑÔð ð €B„JˆyÑÔð ð €B„Jˆ|ÑÔð ð €B„Jˆ ¤Ñ.Ô.ð ð €B„JÐ# R¤]Ñ3Ô3ð ð €B„JÐ! 2¤=Ñ1Ô1ð ð €B„JÐ# R¤]Ñ3Ô3ð ð €B„Jˆ{˜BœMÑ*Ô*ð ð €B„JÐ$Ñ%Ô%ð ð  €B„JÐÑ Ô ð! ð" €B„JÐ" B¤MÑ2Ô2ð# ð$ €B„Jˆ|ÑÔð% ð& €B„JˆÑÔð' ð( €B„JˆÑÔð) ð* €B„JÐ-Ñ.Ô.ð+ ð, €B„JÐNÑOÔOð- ð. €B„JÐ?Ñ@Ô@ð/ ð0 €B„JÐ  "¤-Ñ0Ô0ð1 ð2 €B„JÐ!Ñ"Ô"ð3 ð4 €B„JÐ!Ñ"Ô"ð5 ð6 €B„JÐ%Ñ&Ô&ð7 ð8 €B„JÐ3Ñ4Ô4ð9 ð: €B„JˆÑÔð; ð< €B„JÐ$Ñ%Ô%ð= ð> €B„JÐ6Ñ7Ô7ð? Ð ðDRð Rð RðAð Að Að8ð ð ð,
Qð 
Qð 
Qð
Cð 
Cð 
CðYð Yð Yð	Dð 	Dð 	Dðið ið iðað að að að ar&   