
    Ii"                       d Z ddlmZ ddlZddlmc mZ ddl	Z
ddlZddlmZ ddlZ ed      Zd Z ej"                  d      d	        Z ej"                  d      d
        Z ej"                  d      d        Z ej"                  d      d        Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'y)u   task-2401 — IDS Phase 1 satori 한글 폰트 임베드 회귀 테스트.

silent corruption (한글 □□□, 빈 검은 화면) 영구 차단.
    )annotationsN)Pathz/home/jay/workspacec                L   t         j                  j                  | |      }g }d }||u}|}|r|j                  }d }||u}	|	}|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dz  }
dd|
iz  }|j                  |       |rt	        j
                  d	fdf      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }d	d
|iz  }|j                  |       t	        j                  |d      i z  }t	        j                  d|       dz   d|iz  }t        t	        j                  |            d x}x}x}x}x}x}	}t         j                  j                  |      }|t         j"                  | <   |j                  j%                  |       |S )N)is not)z%(py2)s is not %(py5)sspec)py2py5%(py7)spy7)z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)s)py9py11py14%(py16)spy16r   zfailed to spec z
>assert %(py19)spy19)	importlibutilspec_from_file_locationloader
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprappend_format_boolop_format_assertmsgAssertionError_format_explanationmodule_from_specsysmodulesexec_module)namepathr   @py_assert1@py_assert4@py_assert3@py_assert0@py_assert10@py_assert13@py_assert12@py_format6@py_format8@py_format15@py_format17@py_format18@py_format20mods                    J/home/jay/workspace/tests/design-team/test_ids_phase1_korean_font_embed.py_loadr6      s?   >>11$=DQtQ4tQQ4Q4 7QQQQ4tQQQQQQ4QQQ4QQQtQQQQQQQ4QQQQQQQQQQQQQQQ4QQQQQQQQQQ?4&9QQQQQQQQQ
..
)
)$
/CCKKKKC J    module)scopec                 (    t        dt        dz        S )N
_sc_satori!skills/satori-cardnews/_satori.pyr6   	WORKSPACE r7   r5   
satori_modr@      s    y+NNOOr7   c                 (    t        dt        dz        S )N
_sc_verify/skills/satori-cardnews/scripts/verify_korean.pyr=   r?   r7   r5   
verify_modrD      s    y+\\]]r7   c                 (    t        dt        dz        S )N
_sc_renderz,skills/satori-cardnews/scripts/render_one.pyr=   r?   r7   r5   
render_modrG      s    y+YYZZr7   c                 (    t        dt        dz        S )Nz$skills.hybrid_image.patterns._satoriz'skills/hybrid-image/patterns/_satori.pyr=   r?   r7   r5   hi_satori_modrI       s    7En9noor7   c                   | j                   D cg c]  }|j                         s| }}t        |      }d}||k\  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  d| j                          dz   d	|iz  }t        t        j                  |            d
x}x}}y
c c}w )u;   Pretendard 폰트 파일이 명시 경로에 실제 존재.   >=z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)slenfoundpy0py1py3py6zno Pretendard font at z
>assert %(py8)spy8N)PRETENDARD_PATHSexistsrO   r   r   r   r   r   r   r   r   r    r@   prP   @py_assert2@py_assert5r(   @py_format7@py_format9s           r5   #test_01_pretendard_font_paths_existr_   &   s    "33B1qxxzQBEBu:RR:?RRR:RRRRRR3RRR3RRRRRRuRRRuRRR:RRRRRR4Z5P5P4QRRRRRRRR Cs
   E E c                   | j                   D cg c]  }|j                         s| }}t        |      }d}||k\  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	c c}w )
u1   NotoSansCJK fallback 폰트 명시 경로 존재.rK   rL   rN   rO   rP   rQ   zassert %(py8)srV   N)NOTO_CJK_PATHSrX   rO   r   r   r   r   r   r   r   r    rY   s           r5   !test_02_noto_cjk_font_paths_existrb   +   s    "11@1QXXZQ@E@u::?:33uu: As
   D<D<c                   | j                         }g }t        |t              }|}|rt        |      }d}||k\  }|}|s'ddt	        j
                         v st        j                  t              rt        j                  t              nddt	        j
                         v st        j                  |      rt        j                  |      nddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }|j                  |       |rt        j                  dfdf      d	t	        j
                         v st        j                  t              rt        j                  t              nd	dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      d
z  }	dd|	iz  }
|j                  |
       t        j                  |d      i z  }dd|iz  }t        t        j                  |            dx}x}x}x}x}}d |D        }t        |      }|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}d |D        }t        |      }|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)u:   find_korean_fonts → satori-호환 dict 리스트 반환.rK   z.%(py6)s
{%(py6)s = %(py2)s(%(py3)s, %(py4)s)
}
isinstancefontslist)r   rT   py4rU   rL   )z3%(py11)s
{%(py11)s = %(py8)s(%(py9)s)
} >= %(py14)srO   )rV   r   r   r   r   r   r   zassert %(py19)sr   Nc              3  0   K   | ]  }d |v xr d|v   yw)r%   r&   Nr?   .0fs     r5   	<genexpr>z9test_03_find_korean_fonts_returns_list.<locals>.<genexpr>4   s      :qv{*v{*:s   z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}allrR   r   rg   c              3  ,   K   | ]  }|d    dk(    yw)r%   
PretendardNr?   ri   s     r5   rl   z9test_03_find_korean_fonts_returns_list.<locals>.<genexpr>5   s     8QqyL(8s   any)find_korean_fontsrd   rf   rO   r   r   r   r   r   r   r   r   r   r    rm   rq   )r@   re   r'   r\   r*   r+   r,   r-   r]   r0   r1   r2   r3   r)   @py_format5s                  r5   &test_03_find_korean_fonts_returns_listrt   0   s   ((*E6:eT"6"6"s5z6Q6zQ666666:666:666666e666e666666T666T666"6666"666zQ666666s666s66666656665666z666Q66666666666666:E::3:::::::::3:::3::::::::::::::8%8838888888883888388888888888888r7   c                   | j                   }g }d}||v}|}|r%d}||v}|}|rd}|j                  }	 |	       }
||
v}|}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }|j                  |       |rBt        j                  dfd
|f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }|j                  |       |rt        j                  dfd
f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  	      t        j                  |
      dz  }dd|iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                  |            dx}x}x}x}x}x}x}x}x}	}
g }d}||v }|}|rd}||v }|}|sXt        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }|j                  |       |rt        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                  |            dx}x}x}x}x}}y)uA   KOREAN_FONT_STACK에 Arial/Helvetica/sans-serif 절대 미포함.Arial	Helveticaz
sans-serifnot inz%(py3)s not in %(py5)ssrT   r	   r
   r   z%(py10)s not in %(py12)spy10py12%(py14)sr   )zN%(py17)s not in %(py23)s
{%(py23)s = %(py21)s
{%(py21)s = %(py19)s.lower
}()
})py17r   py21py23z%(py25)spy25r   zassert %(py28)spy28Nrp   zNoto Sans KRin)z%(py3)s in %(py5)s)z%(py10)s in %(py12)szassert %(py17)sr   )KOREAN_FONT_STACKlowerr   r   r   r   r   r   r   r   r   r    )r@   r{   r'   r[   r(   r*   @py_assert9@py_assert11@py_assert16@py_assert20@py_assert22@py_assert18r.   r/   @py_format13r0   @py_format24@py_format26@py_format27@py_format29@py_format16r2   s                         r5   5test_04_korean_font_stack_constant_no_system_fallbackr   7   s   $$AV7V7!VV1 4VVQWWVWYVY9VVVVV7!VVV7VVVVVV!VVV!VVVVVVVV1VVVVVVVVV1VVV1VVVVVVVYVVVVVVVVVQVVVQVVVWVVVYVVVVVVVVVVVVVVV4<4<1441!44444<1444<44444414441444444414444444441444144444444444444r7   c                   | j                          | j                          |j                  }|j                  }d}||v }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}y)	u(   install_silent_fallback_guard 멱등성.)_blocked_fallback_blockedr   )zV%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s._pillow_fallback
}.__name__
} in %(py7)srI   )rR   r   rg   r   zassert %(py9)sr   N)install_silent_fallback_guard_pillow_fallback__name__r   r   r   r   r   r   r   r    )r@   rI   r'   r)   @py_assert6r\   r/   @py_format10s           r5   1test_05_silent_fallback_guard_installs_idempotentr   =   s    ,,.,,.))W)22W6WW26WWWWW26WWWWWWW=WWW=WWW)WWW2WWW6WWWWWWWWr7   c                    | j                          t        j                  t        d      5  |j	                  d|dz  dd       ddd       y# 1 sw Y   yxY w)uF   guard 후 hybrid-image _pillow_fallback 호출 시 RuntimeError raise.silent fallback blockedmatchz<div>test</div>x.pngd   widthheightN)r   pytestraisesRuntimeErrorr   r@   rI   tmp_paths      r5   $test_06_guard_blocks_pillow_fallbackr   D   sU    ,,.	|+D	E e&&'8(W:LTW`c&de e es   AAc                    | j                          t        j                  t        d      5  |j	                  |dz  dd       ddd       y# 1 sw Y   yxY w)u9   guard 후 _write_blank_png 호출 시 RuntimeError raise.r   r   r   r   N)r   r   r   r   _write_blank_pngr   s      r5   $test_07_guard_blocks_write_blank_pngr   J   sM    ,,.	|+D	E E&&x''93DE E Es   AAc                   d| j                   z   dz   }|dz  }| j                  ||dd      }|j                  } |       }|sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      d	z  }t        t        j                  |            d
x}}|j                  } |       }|j                  }d}	||	k\  }
|
st        j                  d|
fd||	f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      t        j                  |	      dz  }t        j                  d|j                         j                         dz   d|iz  }t        t        j                  |            d
x}x}x}x}
}	y
)u0   safe_render_html_to_png 정상 동작 + ≥10KB.zq<div style="display:flex;width:600px;height:400px;background:linear-gradient(135deg,#1a365d,#0a1628);font-family:u}   ;flex-direction:column;justify-content:center;align-items:center;color:#ffffff;font-size:48px;">한글 렌더 테스트</div>z	smoke.pngiX  i  r   zAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}resultrn   N'  rL   )z`%(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.stat
}()
}.st_size
} >= %(py9)s)rR   r   rg   rU   r   zPNG too small: z
>assert %(py11)sr   )r   safe_render_html_to_pngrX   r   r   r   r   r   r   r    statst_sizer   r   )r@   r   htmloutr   r'   r)   rs   r\   @py_assert8@py_assert7r   @py_format12s                r5   test_08_safe_render_smoker   P   s`   ~  @J  @\  @\  \  ]\  \D
[
 C//cS/QF===??66=?;;U;=U=  UFU F*UUU FUUUUUU6UUU6UUU;UUU=UUU UUUFUUUofkkm>S>S=T,UUUUUUUUr7   c                    |j                  dd        t        j                  t        t        f      5  | j                  d|dz  dd       ddd       y# 1 sw Y   yxY w)uC   node binary 부재 시 FileNotFoundError raise (silent fallback 0).zshutil.whichc                     | |d fd   S )N   r?   )aks     r5   <lambda>z>test_09_safe_render_raises_when_node_missing.<locals>.<lambda>Z   s    AtQ r7   z<div>x</div>r   r   r   N)setattrr   r   FileNotFoundErrorr   r   )r@   r   monkeypatchs      r5   ,test_09_safe_render_raises_when_node_missingr   X   s\    (GH	)<8	9 f**>8g;MUXad*ef f fs   AAc                   d| j                   z   dz   }|dz  }| j                  ||dd       |j                  |g d|      }|d   }d	}||u }|st        j                  d
|fd||f      t        j
                  |      t        j
                  |      dz  }	t        j                  d|       dz   d|	iz  }
t        t        j                  |
            dx}x}}|d   d   }d}||k  }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}y)u<   실 렌더 PNG → verify_png pass=True + tofu_score 낮음.zs<div style="display:flex;width:1080px;height:1080px;background:linear-gradient(135deg,#0a0a1a,#0d1b3e);font-family:u   ;flex-direction:column;justify-content:center;align-items:center;color:#ffffff;font-size:64px;">보험 가이드 한글 테스트</div>zreal.png8  r   )   보험	   가이드u   한글expected_koreanhtml_sourcepassTisz%(py1)s is %(py4)srS   rg   zverify failed: 
>assert %(py6)srU   Nmetrics
tofu_scoreg      ?)<)z%(py1)s < %(py4)sassert %(py6)s)	r   r   
verify_pngr   r   r   r   r   r    )r@   rD   r   r   r   r   r*   r)   r[   rs   r]   s              r5   'test_10_verify_png_pass_for_real_renderr   ^   s#    A  BL  B^  B^  ^  _h  hD
Z
C&&tST&J""38Ygk"lF&>=T=>T!===>T===>===T===_VH#========)\*0S0*S0000*S000*000S0000000r7   c                   ddl m} |dz  }|j                  ddd      j                  |       | j	                  |dg      }|d	   }d
}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}|d   d   }d
}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)u;   1×1 blank PNG → file_size_ok=False (silent pass 차단).r   Imagez	blank.pngRGB)rK   rK   )r   r   r   xr   r   Fr   r   r   r   rU   Nchecksfile_size_ok
PILr   newsaver   r   r   r   r   r    )
rD   r   r   blankr   r*   r)   r[   rs   r]   s
             r5   ,test_11_verify_png_detects_blank_placeholderr   g   s    {"E	IIeVY',,U3""53%"@F&>"U">U"""">U""">"""U"""""""(N+4u4+u4444+u444+444u4444444r7   c                   ddl m} |dz  }|j                  ddd      j                  |       | j	                  |dg      }|d	   d
   }d}||u }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d|       dz   d|iz  }	t        t        j                  |	            dx}x}}y)u3   단색 1080×1080 PNG → color_diversity_ok=False.r   r   z	solid.pngr   r   r   )   r      r   r   r   color_diversity_okFr   r   r   zshould detect solid color: r   rU   N)r   r   r   r   r   r   r   r   r   r   r    )
rD   r   r   solidr   r*   r)   r[   rs   r]   s
             r5   &test_12_verify_png_detects_solid_colorr   p   s    {"E	IIe\<055e<""53%"@F(01bUb1U:bbb1Ubbb1bbbUbbb>YZ`Ya<bbbbbbbbr7   c                   ddl m} |dz  }|j                  ddd      j                  |       | j	                  |dg      }|d	   }d
}||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}|d	   }d}||k7  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)uG   tesseract 미설치 시에도 mode='PIXEL-ONLY' 명시 (silent skip 0).r   r   zm.pngr   r   )2   r   r   r   r   mode)z	PIXEL+OCR
PIXEL-ONLYr   )z%(py1)s in %(py4)sr   r   rU   NSKIP)!=)z%(py1)s != %(py4)sr   
rD   r   r   imgr   r*   r)   r[   rs   r]   s
             r5   )test_13_verify_png_mode_explicitly_markedr   y   s    
W
C	IIe\=166s;""3">F&>888>88888>8888>88888888888&>#V#>V####>V###>###V#######r7   c                   ddl m} |dz  }|j                  ddd      j                  |       | j	                  |ddgd	
      }|d   d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)u;   expected_korean 미포함 html → html_string_match=False.r   r   r   r   r   )
   r      r   r   u   <div>영문만</div>r   r   html_string_matchFr   r   r   r   rU   Nr   r   s
             r5   "test_14_html_string_match_requiredr      s    
W
C	IIe\<055c:""3;8O]s"tF(/09E90E99990E9990999E9999999r7   c                   |dz  }| j                  ddddd|      }g }|j                  } |       }|}|r(|j                  } |       }	|	j                  }
d}|
|k\  }|}|sd	d
t	        j
                         v st        j                  |      rt        j                  |      nd
t        j                  |      t        j                  |      dz  }|j                  |       |rt        j                  dfd
f      d
t	        j
                         v st        j                  |      rt        j                  |      nd
t        j                        t        j                  	      t        j                  |
      t        j                  |      dz  }dd|iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                  |            dx}x}x}x}x}x}	x}
x}}|d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)u+   render_one.render_and_verify 통합 동작.zint.pngsupabaseh4_gradient_cardr   u   보험 가입 가이드u'   한 번에 비교하고 절약하세요)brandpatternsizetitlebodyoutput_pathr   z:%(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py2)s.exists
}()
}r   )r   rg   rU   rL   )zg%(py14)s
{%(py14)s = %(py12)s
{%(py12)s = %(py10)s
{%(py10)s = %(py8)s.stat
}()
}.st_size
} >= %(py17)s)rV   r   r   r   r   z%(py19)sr   r   zassert %(py22)spy22Nr   Tr   r   r   r   rU   )render_and_verifyrX   r   r   r   r   r   r   r   r   r   r   r   r    )rG   r   r   r   r'   r)   r\   r*   r   r   r,   r   @py_assert15r]   r2   r3   @py_format21@py_format23r[   rs   s                       r5   %test_15_render_and_verify_integrationr     s   
Y
C))"4<'.W * F
 93::8:<8<8<CHH8HJ8J..8&8.&888888838883888:888<8888<888.&888888C888C888H888J888.888&888888888888888&>!T!>T!!!!>T!!!>!!!T!!!!!!!r7   c                    t         dz  j                         } g d}|D cg c]%  }|j                         | j                         v s$|' }}| }|s~t        j                  d|       dz   ddt        j                         v st        j                  |      rt        j                  |      ndiz  }t        t        j                  |            d}yc c}w )u:   _satori.py 소스에 외부 API URL 미포함 (IDS §0.5).r<   )z
openai.comzanthropic.comgeminicohere	replicatehuggingfacez!forbidden API ref in _satori.py: 
>assert not %(py0)srR   rP   N)r>   	read_textr   r   r   r   r   r   r   r   r    )src	forbiddenurP   r'   @py_format2s         r5   (test_16_no_external_api_in_satori_moduler     s    ::
E
E
GC_I!>1QWWY#))+%=Q>E>9A9AA9%AAAAAAAuAAAuAAAAAA ?s   %CCc                    t         dz  j                         } g }d}|| v}|}|rd}|| v}|}|snt        j                  d|fd|| f      t        j                  |      dt        j                         v st        j                  |       rt        j                  |       nddz  }dd	|iz  }|j                  |       |rt        j                  dfd
| f      t        j                  |      dt        j                         v st        j                  |       rt        j                  |       nddz  }	dd|	iz  }
|j                  |
       t        j                  |d      i z  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}x}x}x}}d}|| v }|st        j                  d|fd|| f      t        j                  |      dt        j                         v st        j                  |       rt        j                  |       nddz  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}}y)u_   verify_korean.py: pytesseract import 실패 시 mode를 명시 표기, 'SKIP' 절대 미사용.rC   z'SKIP'z"SKIP"rx   rz   r  r|   r
   r   r}   r~   r   r   r   zsilent SKIP mode forbiddenz
>assert %(py17)sr   Nr   r   )z%(py1)s in %(py3)s)rS   rT   z*PIXEL-ONLY mode must be explicitly emittedz
>assert %(py5)sr	   )r>   r  r   r   r   r   r   r   r   r   r   r   r    )r  r'   r[   r(   r*   r   r   r.   r/   r   r0   r   r2   @py_format4s                 r5   %test_17b_verify_korean_no_silent_skipr     sL   HH
S
S
UCT8T83T8T83#6TTTT83TTT8TTTTTT3TTT3TTTTTTT83TTT8TTTTTT3TTT3TTTTTTTTTT8TTTTTTTTL<3LLL<3LLL<LLLLLL3LLL3LLLL LLLLLLLr7   c                 h   ddl } t        dz  j                         }| j                  d|      }| }|s~t	        j
                  d|       dz   ddt        j                         v st	        j                  |      rt	        j                  |      ndiz  }t        t	        j                  |            d}y)	u2   _satori.py에 silent except pass 패턴 미존재.r   Nr<   zexcept[^:]*:\s*passzsilent except pass found: r  rR   matches)rer>   r  findallr   r   r   r   r   r   r   r    )r  r  r  r'   r  s        r5   $test_17_no_silent_fallback_in_satorir!     su    ::
E
E
GCjj/5G;>;>>4WI>>>>>>>w>>>w>>>>>>r7   )(__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   importlib.utilr   r"   pathlibr   r   r>   r6   fixturer@   rD   rG   rI   r_   rb   rt   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r!  r?   r7   r5   <module>r+     s   #      &'	 hP  P h^  ^ h[  [ hp  p
S

95XeEVf15c$:	"BM?r7   