
    5)jJ                        U d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddl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mZ ddlmZ ddlmZ  ej0                  e      ZddlZddlmZmZmZm Z m!Z! ddl"m#Z# ddl$m%Z% ddl&Z& e' e
jP                  d	            Z)e)sddl*Z* e*jV                  d
       h dZ,dZ-dZ.dZ/e G d d             Z0da1ejd                  dz  e3d<   g Z4e5ejl                     e3d<   de7fdZ8ejr                  d        Z: ede:      Z;e)e;jx                  _=        i Z>e?e@e?f   e3d<   de@fdZA eeB      j                  d      ZDdaEej                  dz  e3d<    ej                         ZHdej                  fdZIde@de?dz  fdZJde@d e?fd!ZKd"d"d"d#d#d#d$d$d$d#d#d#d%ZLd&dhZMh d'ZNd( ZOd) ZPd*eQd+e@deQfd,ZRd-e@fd.ZSdd/i d0d1d2dd"ddd3d4d5d6d7ddddddd&d8d0d9d/i d0d:d/i d0d"d/i d0gZT ej                   eeB      j                  d;      j                               ZW ej                   eeB      j                  d<      j                               ZX ej                   eeB      j                  d=      j                               ZYd> ZZd? Z[d@ Z\dA Z]dB Z^e;j                  dC      dD        Z`e;j                  dE      dcdFe dGe?fdH       Zbe;j                  dI      dFe fdJ       Zce;j                  dK       edL      fdMe!fdN       Zde;j                  dO      dcdGe?fdP       Zee;j                  dQ       edL      dRfdMe!dSe'fdT       Zfe;j                  dU       edL      fdMe!fdV       Zge;j                  dW       edL       edL       eg X      fdYe@dZe@d[e5e!   fd\       Zhe;j                  d] e% eeB      j                  d^z  d4_      d^`       da Zkedbk(  r ek        yy)du>   Kitmaker web app — Razzmatazz kit builder + audio converter.    N)	dataclassfield)Path)escape)FastAPIFileFormRequest
UploadFile)Response)StaticFilesffmpegz?ffmpeg not found on PATH. Audio conversion and probe will fail.>   .aac.aif.m4a.mp3.ogg.aiff.flac.wav         c                   r    e Zd ZU eed<   eed<   eed<   eed<   eed<    ed       Ze	j                  ed<   y	)
AnalysisJobrawextfnameforce	cache_keyc                  F    t        j                         j                         S N)asyncioget_event_loopcreate_future     (/home/david/assistant/kitmaker/server.py<lambda>zAnalysisJob.<lambda>5   s    7;Q;Q;S;a;a;cr'   )default_factoryresultN)__name__
__module____qualname__bytes__annotations__strboolr   r+   r#   Futurer&   r'   r(   r   r   .   s/    	J	HJKN"3cdFGNNdr'   r   _analysis_queue_worker_tasks	worker_idc                 L  K   	 t         j                          d {   }	 |j                  sMt        |j                        }|r6d|d<   |j
                  j                  |       	 t         j                          w|j                  r7t               }|j                  d|j                  f       |j                          t        j                  t        j                  |j                  |j                   |j"                         d {   }d|d<   t%        |j                  |       |j
                  j                  |       t         j                          Q7 :7 S# t&        $ r%}|j
                  j)                  |       Y d }~Dd }~ww xY w# t         j                          w xY ww)NT_cachedz,DELETE FROM analysis_cache WHERE file_hash=?F)r4   getr   	cache_getr    r+   
set_result	task_doneget_dbexecutecommitr#   	to_threadanalysisanalyze_audior   r   r   	cache_set	Exceptionset_exception)r6   jobcacheddbr+   es         r(   _analysis_workerrJ   ;   s=    
#''))	(99"3==1(,F9%JJ))&1 %%' yyX

ICMMK[\		",,X-C-CSWWcggWZW`W`aaF %F9cmmV,JJ!!&) %%') ) b  	(JJ$$Q''	( %%'sd   F$EF$AE %F$:B
E E:E ?F$E 	F#F>F FF F!!F$c                  K   t        j                         at        j                         }t        j                          t        t              D ]1  }|j                  t        |            }t        j                  |       3 d  t        D ]  }|j                           t        j                  t        ddi d {    t        j                          d ay 7 w)Nreturn_exceptionsT)r#   Queuer4   get_running_loopr5   clearrangeANALYSIS_WORKERScreate_taskrJ   appendcancelgather)apploopitasks       r(   lifespanrZ   S   s      mmoO##%D#$ 0 34T" % 
 
..-
@4
@@@O As   B<C>C?CzRazzmatazz Kitmaker)titlerZ   	_sessionsreturnc                     | j                   j                  d      }|r|t        vrt        j                  d      }i t        |<   |S )Nkitmaker_session   )cookiesr9   r\   secrets	token_hex)requestsids     r(   _session_idrf   k   s?    
//

0
1C#Y&#	#Jr'   zcache.db_dbc                     t         t         S t        j                  t        t              d      a t        j
                  t         _        t         j                  d       t         j                  d       t         j                  d       t         j                  d       t         j                  d       t         j                          t         S )NF)check_same_threadzPRAGMA journal_mode=WALzPRAGMA synchronous=FULLzPRAGMA busy_timeout=10000zPRAGMA wal_autocheckpoint=100zCREATE TABLE IF NOT EXISTS analysis_cache
        (file_hash TEXT PRIMARY KEY, result TEXT, analyzed_at TEXT DEFAULT CURRENT_TIMESTAMP))	rg   sqlite3connectr1   DB_PATHRowrow_factoryr>   r?   r&   r'   r(   r=   r=   {   s    


//#g,%
@CkkCOKK)*KK)*KK+,KK/0KK a bJJLJr'   	file_hashc                 &   	 t         5  t               j                  d| f      j                         }|rt	        j
                  |d         nd cd d d        S # 1 sw Y   y xY w# t        $ r$}t        j                  d| d d |       Y d }~y d }~ww xY w)N3SELECT result FROM analysis_cache WHERE file_hash=?r   zcache_get(%s...) failed: %sr`   )	_db_lockr=   r>   fetchonejsonloadsrD   logwarning)ro   rowrI   s      r(   r:   r:      sx    (""E	|hj  *-4::c!f%$	 XX
  19Sb>1Es5   A# AA	A# A A#  A# #	B,BBr+   c                 @   	 t         5  t               }|j                  d| t        j                  |      f       |j                          |j                  d       d d d        y # 1 sw Y   y xY w# t        $ r$}t        j                  d| d d |       Y d }~y d }~ww xY w)NzFINSERT OR REPLACE INTO analysis_cache (file_hash, result) VALUES (?,?)zPRAGMA wal_checkpoint(PASSIVE)zcache_set(%s...) failed: %sr`   )	rr   r=   r>   rt   dumpsr?   rD   rv   rw   )ro   r+   rH   rI   s       r(   rC   rC      s    
FBJJXDJJv./ IIKJJ78 XX  F19Sb>1EEFs5   A0 AA$A0 $A-)A0 -A0 0	B9BBr`          )s16s16les16bes32s32les32bes24s24les24befltfltlefltbe   >   r`   r|   r{   c                     | j                         } t        j                  dd|       } t        j                  dd|       } t        j                  dd|       } | j                         xs dS )Nz[<>:"/\\|?*\x00-\x1f] z\s+z\.+$ zUnnamed Kit)stripresubnames    r(   sanitize_namer      sU    ::<D66*C6D66&#t$D66'2t$D::<(=(r'   c                 <    | j                  d      }|dkD  r| d | S | S )N.r   )rfind)r   rX   s     r(   	strip_extr      s&    

3A1u48&$&r'   input_bytesr   c                 *   t        j                  |d      5 }|j                  |        |j                  }ddd       dz   }	 t	        |      \  }}}}|t
        v r|nd}	|t        v r|nd}
|
dkD  rd}
dddd	|
   }|j                  d
d      }ddd|d|d|g}|	|k7  r|dt        |	      gz  }|dgz  }t        j                  |dd      }|j                  dk7  r-|j                  j                  d      dd }t        d|       t        j                          }t#        j$                  |d      5 }|j'                  |	       |j)                  |
dz         |j+                  |       |j-                  |j.                         ddd       |j1                         ||fD ]  }	 t3        j4                  |        S # 1 sw Y   xY w# 1 sw Y   ExY w# t6        $ r Y @w xY w# ||fD ]'  }	 t3        j4                  |       # t6        $ r Y %w xY w w xY w)zoConvert any audio to Razzmatazz-compatible WAV (PCM tag 1, preserve
    sample rate, 24-bit max, 1-2 channels).FsuffixdeleteNr   r   r|   	pcm_s16le	pcm_s24le)r`   r|   r{   pcm_r   r   z-yz-iz-fz-acodecz-aczpipe:1Tx   )capture_outputtimeoutr   replace)errors   zffmpeg: wbr   )tempfileNamedTemporaryFilewriter   _probeALLOWED_CHANNELSALLOWED_BIT_DEPTHSr   r1   
subprocessrun
returncodestderrdecodeRuntimeErrorioBytesIOwaveopensetnchannelssetsampwidthsetframeratewriteframesstdoutgetvalueosunlinkOSError)r   r   tmp_ininpathoutpathchsrbd_dur	target_ch	target_bdacodecraw_fmtcmdrerrbufwfps                      r(   convert_audior      s     
	$	$C	>&[! 
? voG!&>BD 00Ba	 22B	r>I!{DYO..,tVT7IvN?E3y>**CzNN3tSA<<1((///3DS9C#/00jjlYYsD!ROOI&OOIN+OOBNN188$	 "
 ||~'"A		! #A 
?	>2 "!   '"A		!  #sg   F:C-G" 1AGG" "G:GGG" 	GG"H+H H	H	
HH	Hpathc           
          t        j                  ddddddd| gddd	
      }t        j                  |j                        }d }d|v r+|d   j                  d      }|rt        t        |      d      }|j                  dg       D ]s  }|j                  d      dk(  s|j                  dd      }t        |j                  dd            }|j                  dd      }t        j                  |d      }	|||	|fc S  ddd|fS )Nffprobez-vquietz-print_formatrt   z-show_streamsz-show_formatT   )r   textr   formatduration   streams
codec_typeaudiochannelsr   sample_rateiD  
sample_fmtr}   r`   )
r   r   rt   ru   r   r9   roundfloatintSAMPLE_FMT_TO_BITS)
r   r   datadurdsr   r   fmtr   s
             r(   r   r      s   	D'?FO		$	4A ::ahhD
C4Nz*a!$CXXi$55')z1%BQUU=%01B%%e,C#''R0Br2s?" % eRr'   samtempl)rx   typeparams
   seqmod)steplenseqsteps
seqkeytrigseqquantT)rx   r   r   sequence   drumsettings)chokegrploopmodemaclaunchtoggstackfiltmodemacpitchmodplaythru	fx3enable      ztemplates.jsonzglobal_fx.jsonzdefault_seq.jsonc                 b    dj                  d | j                         D              }|rd| dS dS )Nr   c              3   V   K   | ]!  \  }}| d t        t        |             d # ywz=""Nr   r1   .0kvs      r(   	<genexpr>z render_params.<locals>.<genexpr>  s+     J>41as"VCF^,A.>   ')z<params />z	<params/>)joinitems)r   attrss     r(   render_paramsr    s2    HHJ6<<>JJE#(XeWB9k9r'   c           	         t        | d         }| d   dk(  r
d|d<   d|d<   | d   dk(  rd|d	<   | d   d
k(  rd|d<   d|d<   d|d<   | d   dk(  r8||d<   |rdnd|d<   |rdnt        |dz        |d<   |rdnt        |dz        |d<   | d   dk(  r(dD ]  }|j                  |d         d|d<   d|d<   d|d<   | d   dk(  r|n| j                  d      xs d}d| d    d| dt	        |       d | d!    d"	d#t        |       g}	| j                  d$      r|	j                  d%       |	j                  d&       d'j                  |	      S )(Nr   rx   r   r   	pitchsemi	pitchfine   i  envdecay	   vfxdistfx1sendfx2send   selpadr   Mutei r   gaindbpanposr   )macpitchmacdelay	oscwavmixmodeldistamtfilenamer   z        <cell row="z" column="0" synth="z" filename="z" type="r   ">            r               <sequence/>        </cell>
)dictr   popr9   r   r  rS   r
  )
cellr   synth_idvolumepanmutedr   r  r   liness
             r(   render_cellr.    s   T(^AE{a++E{a*E{a)))E{b(AA&	 %f5"+=( aeC"Ho(E{bAEE!TN *+.Uq(Htxx
/C/IrE
d5k]*>xjU[\aUbTccklpqwlxkyy{|
}Q'()E xx
./	LL"#99Ur'   c                     t         fdt        D        d       }|r|d   ndddddd}|r|j                  dg       ng }d	  d
dt        |       |rdndg}|D ]=  }dj	                  d |j                         D              }|j                  d| d       ? |r|j                  d       |j                  d       dj	                  |      S )Nc              3   4   K   | ]  }|d    k(  s|  yw)seqnumNr&   )r  r   r1  s     r(   r  zrender_seq.<locals>.<genexpr>6  s     G-a81F-s   r   101601)notesteplennotestepcountmidioutchanseqplayenableseqstepmodeeventsz        <cell seqnum="z" type="noteseq">r"  z            <sequence>r#  r   c              3   V   K   | ]!  \  }}| d t        t        |             d # ywr   r  r  s      r(   r  zrender_seq.<locals>.<genexpr>A  s+     Jztq!A3bA 02zr  z                <seqevent r	  z            </sequence>r$  r%  )nextDEFAULT_SEQ_EVENTSr9   r  r
  r  rS   )r1  seqr   r;  r-  evr  s   `      r(   
render_seqrA  5  s    
G-G
NC!S]dS(FF '*SWWXr"rF
 (9:
}V,-.$* 0IE
 JrxxzJJ1%;<  ./	LL"#99Ur'   c                      g } t         D ]i  }| j                  d|d    d       | j                  d|d    d|d    d       | j                  dt        |d	                 | j                  d
       k | S )N        <synth id="idz" name=""/>z(        <cell row="0" column="0" synth="z" filename="" type="r   r!  r"  r   r$  )	GLOBAL_FXrS   r  )r-  fxs     r(   render_global_fxrG  I  s    E*2d8*K@A?4zI]^`ag^h]iiklm|M"X,$?#@AB&'	 
 Lr'   c                 H   t        |       }g d}|D ]  }d|d   z
  }t        |j                  d            }|j                  dd      }t        j                  |t        d         }t        |j                  dd|d   d	z                d d
 }	|rd| d|j                  dd       nd}
| }|j	                  d| dt        |	       d       |d   D ]A  }|j	                  t        ||
||j                  dd      |j                  dd      |             C  |j                  t                      t        d      D ]  }|j	                  t        |              |j	                  d       |j	                  d       |j	                  d       dj                  |      dz   S )N)z&<?xml version="1.0" encoding="UTF-8"?>z
<document>z    <session version="4">   	slotIndexr   r   tomlabelzPad r   r|   z	\Samples\\r   rC  z" name="z"/>cellsr*  r   r+  r`   z        <midimap/>z    </session>z</document>r%  )r   r2   r9   SYNTH_TEMPLATESrS   r   r.  extendrG  rP   rA  r
  )kit_nameslotssafer-  slotsi
has_samplestypetemplate	disp_namesample_pathr,  r(  r1  s                 r(   	build_nnrr[  S  s   "DaEk""$((:./
'"&&uoe.DE!$((7d4;Lq;P:Q4R"STUXVXY	JTD6DHHZ,D+EFZ\*2$hvi7H6IMNW%DLLT;DHHXq<QSWS[S[\acdSeglmn &  
LL!#$)Z'( 	LL%&	LL!"	LL99Ud""r'   z	/api/pingc                  
    ddiS )NokTr&   r&   r'   r(   pingr^  m  s    $<r'   z/api/session/saverd   r   c                    K   t        |       }|	|t        |<   t        t        j                  ddi            }|j                  d|ddd       |S w)Nr]  Tr_    ' laxmax_agehttponlysamesite)rf   r\   r   rt   rz   
set_cookie)rd   r   re   resps       r(   api_session_saverh  r  sS     
g
C	#DJJd|,-DOO&Z$Y^O_Ks   AAz/api/session/loadc                    K   t        |       }t        j                  |i       }t        t	        j
                  |            }|j                  d|ddd       |S w)Nr_   r`  Tra  rb  )rf   r\   r9   r   rt   rz   rf  )rd   re   r   rg  s       r(   api_session_loadrj  |  sP     
g
C==b!DDJJt$%DOO&Z$Y^O_Ks   AAz
/api/probe.filec           	      d  K   t         j                  j                  | j                  xs d      d   j	                         }|t
        vr&t        t        j                  dd| i      dd      S | j                          d {   }dd l
} |j                  |d	
      5 }|j                  |       |j                  }d d d        	 t              \  }}}}	||||	xs d|t        |      d	 t        j                   |       S 7 # 1 sw Y   HxY w# t"        $ r Y S w xY w# t$        $ r[}
t        t        j                  dt'        |
      i      dd      cY d }
~
	 t        j                          S # t"        $ r Y S w xY wd }
~
ww xY w# 	 t        j                          w # t"        $ r Y w w xY wxY ww)Nr   r   errorzUnsupported format:   application/jsonstatus_code
media_typer   Fr   )r   
sampleRatebitDepthr   r   size)r   r   splitextr   lowerAUDIO_EXTENSIONSr   rt   rz   readr   r   r   r   r   lenr   r   rD   r1   )rk  r   r   r   fr   r   r   r   r   rI   s              r(   	api_prober|    s    
''

4==2F
3A
6
<
<
>C
""

G/CC5-I#JK$'4FH 	H		
C	$	$	$C	>!	vv 
? ,BCqH
	IIdO) 	>	>&  		  H

GSV#45$'4FH 	H	IIdO 		H	IIdO 		s   B F0DF0D=F0%D ,DF0D	F0	DF0DF0	F(+E>FF E/.F0/	E;8F0:E;;F0>FF F-FF-	F*'F-)F**F--F0z/api/lookupc                    K   | i S | j                  dg       }|si S i }t        5  t               }|D ]A  }|j                  d|f      j	                         }|'t        j                  |d         ||<   C 	 ddd       |S # 1 sw Y   |S xY ww)z?Bulk lookup: returns {hash -> result_or_null} for known hashes.Nhashesrq   r   )r9   rr   r=   r>   rs   rt   ru   )r   r~  outrH   hrx   s         r(   
api_lookupr    s      |	XXh#F	
C	XA**Ethj  CF+A  
 J 
 Js"   #B3BB7
BBBz/api/analyzeFr   c           	        K   t         j                  j                  | j                  xs d      d   j	                         }|t
        vr&t        t        j                  dd| i      dd      S | j                          d {   }t        j                  |      j                         }|}| j                  xs d}|r4t        j                  ||z   j                               j                         }t        |||||	      }t        j!                  |       	 t#        j$                  |j&                  d
       d {   }|S 7 7 # t"        j(                  $ r& t        t        j                  ddi      dd      cY S t*        $ r6}	t        t        j                  dt-        |	      i      dd      cY d }	~	S d }	~	ww xY ww)Nr   r   rm  zUnsupported: rn  ro  rp  r   )r   r   r   r   r    r   )r   zAnalysis timed outi  )r   r   rv  r   rw  rx  r   rt   rz   ry  hashlibsha256	hexdigestencoder   r4   
put_nowaitr#   wait_forr+   TimeoutErrorrD   r1   )
rk  r   r   r   ro   r    r   rF   r+   rI   s
             r(   api_analyzer    s    
''

4==2F
3A
6
<
<
>C
""

G}SE-B#CD$'4FH 	H		
Cs#--/IIMMRENNI$5#=#=#?@JJL	
#3e5I
VCs#H''

C@@  A H

G-A#BC$'4FH 	H H

GSV#45$'4FH 	HHsa   B G EBG $E <E=E G E 6F==G ?F=+F82F=3G 8F==G z/api/convertc           	        K   t         j                  j                  | j                  xs d      d   j	                         }| j                          d {   }	 t        ||      }t        |dd| j                  xs di      S 7 /# t        $ r6}t        t        j                  dt        |      i      dd	
      cY d }~S d }~ww xY ww)Nr   r   z	audio/wavzX-Original-Namez
sample.wavcontentrr  headersrm  rn  ro  rp  )r   r   rv  r   rw  ry  r   r   rD   rt   rz   r1   )rk  r   r   wavrI   s        r(   api_convertr    s     
''

4==2F
3A
6
<
<
>C		
CgC%!2DMM4Q\ RT 	T 
  g

GSV#453SeffgsB   ACBC)B C	C+C :C;C CCz/api/export)defaultkitNameconfigfilesc                    K   t        |       xs d}t        j                  |      }|D cg c]  }|j                  d      s| }}|s#t	        t        j
                  ddi      dd      S t        j                         }t        j                  |dt        j                        5 }d	| }	t               }
|D ]R  }|d   t        fd
|D        d       }|d|d<   &|j                          d {   }t        |      dk(  rd|d<   Rt        j                   j#                        d   j%                         }	 t'        ||      }t        t+                    xs d|d   dz    }|dz   }t        |      dkD  r
|d d }|dz   }d}|j%                         |
v r7| d| }t        |      dkD  r|d d }| d}|dz  }|j%                         |
v r7|
j-                  |j%                                ||d<   |j/                  |	 d| |       U t1        ||      }|j/                  | d|       d d d        t	        |j3                         ddd| di      S c c}w 7 m# t(        $ r Y w xY w# 1 sw Y   CxY ww)NMyKitr   rm  zNo samples assigned to any pad.rn  ro  rp  wzSamples/c              3   B   K   | ]  }|j                   k(  s|  y wr"   )r   )r  r{  fns     r(   r  zapi_export.<locals>.<genexpr>  s     B1r1AQs   r   r   r   padrJ  r   r      r   -/z.nnrzapplication/zipzContent-Dispositionzattachment; filename="z.zip"r  )r   rt   ru   r9   r   rz   r   r   zipfileZipFileZIP_DEFLATEDsetr=  ry  rz  r   r   rv  rw  r   rD   r   addwritestrr[  r   )r  r  r  r   rR  r   filledr   zf
sample_dir
used_namesrT  uploadedr   r   r  baseout_namer   stemnnr_xmlr  s                        @r(   
api_exportr    s     !,WDJJvE4A!%%
"3aF4

G-N#OP$'4FH 	H **,C	c7#7#7	8Bv&
U
Dj!BBBDIH#%Z  'C3x1}#%Z ''""2&q)//1C#C- !2/PSk9JQ9N8O3PDf}H8}s"DSz&=F.."j0q)t9s?:D"V4=! .."j0 NN8>>+,'DKK:,az2C8C F D%(
tfDM7+O 
9R CLLN7H26LTFRW4XY[ [_ 5  (  % 
9	8so   )I>IIA I>'AI22I3AI2<I"BI2AI20/I>I2"	I/+I2.I//I22I;7I>r  static)	directoryhtmlr   c                  6    t        j                  dddd       y )Nz
server:appz0.0.0.0i`"  T)hostportreload)uvicornr   r&   r'   r(   mainr    s    KK94Er'   __main__r"   )l__doc__r#   
contextlibr  r   rt   loggingr   r   rb   shutilrj   r   r   	threadingr   r  dataclassesr   r   pathlibr   xml.sax.saxutilsr   	getLoggerr,   rv   rA   fastapir   r   r	   r
   r   fastapi.responsesr   fastapi.staticfilesr   r  r2   which
_ffmpeg_okwarningswarnrx  	PAD_COUNT
GRID_WIDTHrQ   r   r4   rM   r0   r5   listTaskr   rJ   asynccontextmanagerrZ   rV   state	ffmpeg_okr\   r&  r1   rf   __file__	with_namerl   rg   
ConnectionLockrr   r=   r:   rC   r   r   r   r   r   r/   r   r   COMMON_ROWSru   	read_textrO  rE  r>  r  r.  rA  rG  r[  r9   r^  postrh  rj  r|  r  r  r  r  mountparentr  r&   r'   r(   <module>r     s   D    	   	 	         (  #g!  < < & +  ,&,,x()
HMMSTU 	
  e e e )-% ,$&tGLL! &(c (0     )H= 		   	4T	? C  x.
"
":
.!%W$ %9>>"" 	 	 	F Fd F RRRR	  q6 ! )'
'u '3 '5 'T 2 zR0r!-%268qa!A1[\3^ _
b1
b1
b1	 $**T(^556FGQQSTDJJtH~//0@AKKMN	TZZX 8 89K L V V XY :
D(#4   
G 4   	G   ,'+Cy *  < -4  $ .)-c% HJ H4 H H0 .)-c gJ g g -9s)"2.8[8[8[ 
8[ 8[z 		#{T(^%:%:X%EDQX`	 aF zF r'   