From 50dafc4c60cfd4183bdedcd86fcd9b6b932c6a0b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 20 Aug 2013 00:30:26 -0400 Subject: [PATCH] initial extension --- .gitignore | 1 + TODO | 5 + images/icon-128x128.png | Bin 0 -> 15523 bytes images/screenshot.png | Bin 0 -> 44936 bytes images/small-tile.png | Bin 0 -> 14347 bytes js/mpc.js | 187 +++++++++++++++++++++++++++++++ js/tcp-client.js | 229 ++++++++++++++++++++++++++++++++++++++ launcher.js | 10 ++ main.html | 125 +++++++++++++++++++++ main.js | 236 ++++++++++++++++++++++++++++++++++++++++ makedist.sh | 42 +++++++ manifest.files | 6 + manifest.json | 20 ++++ 13 files changed, 861 insertions(+) create mode 100644 .gitignore create mode 100644 TODO create mode 100644 images/icon-128x128.png create mode 100644 images/screenshot.png create mode 100644 images/small-tile.png create mode 100644 js/mpc.js create mode 100644 js/tcp-client.js create mode 100644 launcher.js create mode 100644 main.html create mode 100644 main.js create mode 100755 makedist.sh create mode 100644 manifest.files create mode 100644 manifest.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4c4ffc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.zip diff --git a/TODO b/TODO new file mode 100644 index 0000000..7d7c32d --- /dev/null +++ b/TODO @@ -0,0 +1,5 @@ +make UI not so crappy + +support keyboard shortcuts + +playlist support diff --git a/images/icon-128x128.png b/images/icon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..4238d24e87ab027d20fb20780bf4b95e7bbd1c2b GIT binary patch literal 15523 zcmZvjWl$V#l!XU(cXtaO2<{RH8riKp>QF(h|zRYruayJS+$VQO~QS2OL2BP?iz{RZb8e0SBc6CFWPguGv;bd?J~v`kuwkR6WZ?Yiz`eY~c57#NUgxB0sd)+T7RIPZNx z9w6UBeZFl!81#RW5x|JVh#d&xM(HERjm)Y@oPp94Me2O7&}lH+`)2X^_V%vEY}Wkv z_=F)6pGl`R5v@?+%-!8p{Y%k<08y+Y2Bht(=>9!bdFD%am?bCQA-;4#&c?ezjWo4b zKWB+tzjX1eDF*>afzOKF|Kq_QO}M3Ilg#2X0W~=aLwG7}n9*Jo$E$P+61!)qSd8lE3A@q3?3P$hcjXEvChiP^$fC( zKo{Cz1RgP&0`B}KpB*B(4E6*X#zE(~-EZejWkkWFeSIN0)rAy=Qm9fU<0ki(+g*w1a(rs(&CC>ZI@^_P zeA&OF{AoCU8d!J#=(e!?a5`P8S%li$b@&~Ee)Q0Bf&7+`^D03UmW%fMb{VOt`!Kmu zYv&Ip50fLuy^#swl>B zLK^__&wFsn0f#|LaD04h9!9|MZt~#h z@YMYI_J|`8x*iX!iO0a+#Nt>1m*NBoSo$tter zC~eAQ!sJ0@zw*mF7faig4`w(tp1y|>c`s@pp-f?av5?1h=qA7UJ0vlDN(}er`Hb@Qul!GZUQQwe77)`r3H1@TXE|WGIg6Aq=OU&f)pE%h%!R z8y!~U*Ko=F{tmDuwT!Z*ssZadv$xjGK{2AS>!^DDg0A;jL-h}+-5Izp34fF;aYoiI z<0Ifh!UxufzEWaP#=(<}%l9h**Ky{EGtD-+^Sp8kjy8(yr*cG!z86B`PDCNa?;RdV zl*fToz)mX>dzrP*2e(k>de813CYP1qU!Vih%0Asfoj{S3=*QDS0PWI2%ZxOt>a*`{M$)Q{tI! z#|)XCgGW%uGH`h=d^_A*NZnyQ)Z1CzG&3fM6%8}mqdNzaT`f#W$9MLnD1G0xZDI`C zAKUi!_UH>?JL(sDZeA|Ba_&wRCm|O&xE;%&9Sb6m7;U&m1ndWmzeb zWSpM%QfyWmV`21pGf|ogTZ`_0r1`lWc6@Wz|6&9&f#bpDI>1PMwf5hsBF4;H9S&CYEc z6oJrrS!4Ru-daznmgEKdV zIB#mv@blsVyXVTS$QuhIBjZ@%s`iit+6t&*K0v@xq3ufhCinjYjkQ`aQ z)ZFz-U74((93E;+*i%v3Wj2w+^WrZfY2?{{HdD6UvzL2z`%_KZ)xk!)Po-+IC3wMP`|s%8Heq`z>*$l_<` zihHF{&* z426YfAXr?I7D_?#a#-f#Q6T^QbzZeC(>C3*g7+k9cKatcaxR2@@hj{YF}Ghk8*(`I z`6Uts8%m#^{`;j4ZlhVvbIU;xg+Z+;f(%1t%Rb>(ZqDZ3<3KXJ)r4og^!6k)LPN+E zC)<$U(!e)_V7r`Okbja?x@b_=ZN7F6LBGAbcN}GIsy6C_t!%#@$sK*4d^I>lBUYOO zsZi?nP_03Qi~N==9CC4m6>PH0D1N`jt89I?BreqS`$y?!yCSWq!H+}dYX2Spd1Q|aK@9$1IJDr|%kaU?Qsa0Znqa@M-~Nx=`}_ED^I#531A~izu)9D) z5ZnFoNA7l*EFucJ82xNwm>nZF<>ewhc>AaDJ9`B)GstHjiF@XNxecZ+_PB`^IY~X+ zm#;+^b=D;`xul_y7#x1+_fPpIZE{nDC50|yJbu`GT07xL|+*#LziIrijR~L8~`=rjK6Sk0k;rGynAEsp5Oo(V!r`35|$a)4z z`cQ5wy|p1noACCe=of+xi9)}3r)?!NH9a%-Pcm{!`zGtc=jZ;u`Gn9(6h&#`02Qbm z(FgkR=cSv^o=L3mJ5e9!a)URw)MVOdwq9E*n;&tBYJ`VC%tCsV@0pD>1KgK?sAkZp z1z7J*iPuoF$xLysuC6`dJec8*7ab2X^YdmJ>Z;|(r^ni~g>&RQSN&N1`LRM@nQ&pw zww6$1cA81)!EQOLq2TjuA@lL{J95WL|Jh4ezd&W{T@^*adCHJ#2!@a;83y*e#``#x z6y}$FBhy4H8UK)4*UMA(qJ<&{X+rp-UDMtDfyWS)4fj`) zm)K}&S=UqW$LnO?9{!u_n9a(ag%Fn7QkCa>NEQjDRT`ElLTnVT{lm!fn)OY5JDr9qIeN!pM2$u*FB+r?= z8B89RBNdKGNMUk{y^VukwoP^b8qL#{2HEAtih#1foGv`rt%UBTQ1t6JJUvs+C^xk6 z&iny{tQFY2g=F&y{x{C}66`P|^jL7qUb4>ZN`p<3nbycok^3I#mGQErW@nIwwbi9? zVXK4;b!2*J1qHE#{BnsoBPcGt6!XtP!6o}MG-_Qe0f<# zg}mP@nJ`Vr<(%2x7Jan3!q)5+j<5m6Z8U7~hCs^R?W|%Sr+h&oa8B#i+*a*?B)qb^ z8e2Z)Y!{i2W-kBC$aaNf(8+)sIS~4Fhd$H=I|lnaA02+%0~Uj$I?9rVp6=9c)xgwU zx7~wX_;nlYTk)*V_RZptmD<9e6@77K=(CQEbJf5 zS+Grlgri*o31@jW-Ymw;)u_zVSoXZSfg!>>@n@fs0-9rrxlAVr@rGq!Msp82~N zWr*_`-H0eT2yO~rWMX2br70X}b-7YZCM)&YFGm=4eFl<5i~FFa)>m~*&2;N6<7@~f zZUYDeeW2JRh~8AU8bZOW5#{aw`Y4UldvE3TI)~>PR=se6JkLg5M6ujq$H*WapBPkn zY>jUJOYQC#29sWGNSojDj%YJTCOCL4IGHd$_sS7fgrM5W)+FC)Pf9q<%1d2Y+>2HR zONDU5hRTDif+6;6D!Uz_Cu?)zTxQ1P0fC^kY8O?@LVB%fO}G2oFk~J(H{uSPN{Jw& z0H_V(V35_9fFYC!&jKHR1|C+-E9-%|Ig5lumF6EknBjAtb~eLw<5_ok>agi^C>%HU z7j}z@OiIQN2mcqH#n7n@WR3Aq%h&2N_eMJtE%j;gM<_=jbl#K9AIP(uq1($~6bAMX z`q~U6hTqD@TDbYvHq|6_@HW@usmbnCA1yQKF_kQ@-RS;rbd=^>kJBrz(1Q0%COk2H zGYKhd6xKZidsDN#yB?WPac5}*Z_Di9CD2E<>8h05 z6YU4xmy3R>NVcoy1~!b13sD(tHI^jm{dw)r$7Qdl7Q$4RPEZ%dHTd)M^Yn!t&uL#E zilYd5Az5so52nm|J6EoFHVt5Y{qZ#lw1G5$9V6hdfFxvq)(%+6R#Xm5hO7`=3`F0p z)5=qBJ;gruNj)Q3HD7JCEBL`H#bq1zMd|7zmZVOL$z@bsIx0}j(A z9~>iYBX1*%l>ffRmD*8Y3F;-j6zcx__pgYI((d8SoLk6A6Uyy=I)XQL7u&uSjb`J$k-V>*+-C*bZ^FdNr}IWe67LT@8D(W3}a0kcO%}%e5=Dgq1DQML|7GfWD z3aM9V^-but{jDt7%c<-N^bwNUsMV8{k!jVwcV4DRL2f1?VVLR0`+Dm*Z{y(xY0#U(xKhiseF2#>ugwok*K7VC zZo zt^cXyJY$DT{QKp);*?1AoI0wcp#i=EsPRi!6n21T^u;^S`U48lXXBPS%N(<~{ z94qkpo4wJAiNk!1iJmT3YjFj|h-oa(U1Ww3{4tiX?8@5F|Ba5xc;I@ECnnekALtUt zxi{tbvS^me!S0{(~=p}T|);s!NJvH*(1D8d%R)(`!Imtl}&@bss^a}9k@N%>43r47%QGuzG1 zESt)XWDh3&!)EST8GcKY$qN1G+H1K~Hi%iyG;VkM>Q0~$X>&q_TS>0 z%`dWws4)QpwZeLv-}dGC*+o`1($daOQl_L`#6U@3{r@Xpn~)ogK2qxJkJ)>Bb9u(5$4Y8yYCx4@D+A0Hpj({2J8s1h8h z>BsSPn%a@c5w`lf3@;yUq}pKKbVm{n&WTNFnR_fTd)|PO4C)=X;JV0{ruwK-GQsDt z42RAZ1JWTwG3V+B-?W`{EbP$~RtJ~`NPpN)G#6rpuI}Gf1GQ$751y~Xbh6%;U$$&f z~SIY-NTAQka-sqy{k_`erX=Iy(vf(6H$flnFHdu-V!7K zSV~DnMP5w}M_C3K)?bO)+rO4 zg=awJVgZ6Jkn7L!*v$r+@Ouar26;VxYYim1n$mC#b4D7ElW{e%wT;bPSyd;YnhZ1K z``Z~Y$P-?+5K3D2?yAg$!<;1axANnYedmcT;xy}I%_d4=0aXIZD>SG$%Pk$4EbrG3 zV%v$}{%F8swCuMkN}U`_8GEopidJSBVWaf+2neZtX?T6+?n2-htYzxF3}rP;Hz($a z7FP@xoI9BiCkUtrcwC~Z3|CWEr!2(y^9g~WBNZZ$ZEdla=ob{9VEy1s9=-8@dW}TB zQv5JAn((Wm(%jH?r_gm=tnN93$#n2=fCGf=q`*V_E+9UMAcoxIhM-mc!6|A-9d2l}T9xLP~+ z^zL9Nlh;Q+Z)dPHxAf(Z4OxDgTAd<-!n76Ms8rpRhg>+t`fJD^yCLNR$l7lid zrd1K&fFTTEv=~drv9YzCgRx>2fS}X;cF}Q9=6l2%+RsVFd9gm4ET4gjzn+8y!}z3& z@wb@BzysXavkKwa6N-n_$0;$z-j$%-`ZUq&YX^TcfZ9?MGS2V*d!sA1)FUyymiohc z(qXCN#{v0B9FrJ$PFqDuX}ikjru8o2&wt&DS|=21K1K^w2a^FcKoe+O0dq zq2)?nYM2smbwd(?Ck37>iEOW13U13*7f=BcV#4goIu5kRL8rSZ$R6T0Vpb6^EKy8G zSh_X@>eVcO{|2&pwj-*%igkqe>MGZKJasr(p6FTDV(+#O0m1kYRU_n(0=XN1>o(tF zGJIiS0hdx-QhFTcJ^ymU9j?g2fN{^vj2jZq^5Tfv`|unAB%BC!(ujkjoD9 z8W1K=42<jL?cuG7FEG2=jY1GTM&9{kpn9?#f z`2;JK;%=<2FqaD>k^p5258OXR3Tc?+%h=z%v_PpCVgcy&4fV=eYFePE%LhMyI(QVZ zel{SrLbyb*o@V+~^4M>3TG`tVIuRGir3EddBVY}-MO>+T{LnP*HiUBgVmKjao;|uj z5%`l11jTiE>#{mRfs*gBFD^ET7a?QgcCp;IYc(4gPgA?h^uwG?5Bn%-*fi+(^U4Y# z2&nBPrjVpvtI>}_OOi$eY*V1rZp`jXb`w}JX?N*0DpE*pWnB-8R}qpha#>EM zQyF&%h|{H(1SAc8CF(s6U*EA*q2LVr)?v7H37K#5(W_T#ig>^KMn*;%Ha}o>`R;#L zJT~r3xy}0bP1B*aLd&^J#n-mBhS{>5Y>2^g66V5aH}eMj%{5~~;-Pl@W+Neux}2Yz zlPE3E^q^Ft_N)`s6S$jGS^F_5$fVnRIh5YPXruJ-1&=wf8lBS#LsqY^=(oLNeG28) zYDbdGE2eg%Z`lhLa7-hKv^zonH7 zh#KpiR#XcJV7z5myevQDr(ssSs{@*&DS)<9)RdZzSXg2nA7$jP4>)MfR9 z_eko<)gLw$PbW52)2oYM8jI{`EWQh!01Y$9<(-< z3or`%&@`<-pZUFaDZbxWu;pQ#wv(8q;fM9qU+s7l(=)xkA~5nH!Bcp=w;V+12DVx* zxR#jwblL&m6lQew9?ijs z7^=|yp6V%Vfxztp4*mkI?|X-noKs5-hqD4HrK*_B4Eew_S=Fw@#T#< zgUjh1PUw68^^;Hb%X!-*+ylQciH6Md>}+2mgGz)ciy?%~B@-$^MZ;{p1=_SGGKI`@ zsTu|pw3ey1clOt_H&Kcaxqp{={gn{ArZrVUsdhd*>!PACT+GK-nW;1Xmt*oolRyS z+f~%lD1s_!Jo|rh4o-E0eyknSQ!Tm*0ynp_*+HsJ84sO=2ZgOVl z*VWLWBu}fvPcQV7?QWLD{SD8R>VAQD0;}h=>+IM0{9bp+@*8MzBb`UC3mqacv6CU- z_@rK-rV!Th8YX~0EV;Dw6Y1mn#p9dr$4+Sr4at2%UfnYChwnqxp{Uv&C&Osnzy#H8$`h|=iEtwwI!*t_?vMI+BpBai2b7HL0HCveWhOz5nh4`xBf7E@Q`vXaaNlm7t48L@Xxe%#+9b+Xezr2X^xQRb*rur8FRy+G(%FNy+>zHEX&hvE^c@ z%}HqY>nr7vDdp8ydHL}oj4xlj6NXJ!oQQYO4cT3|GNP-r>-PH|HvK=wfH^g|wH9q4 zx!UDOIVa-+q}>jtU=9qlEOUSBO}W<4cMfkUZsARyJYcL}$WK(J3PrzbPBmrNTyY_v zkfp}7`s48Wc-0CRTf{O_Xk0wm==$TL*I}_9*S8U7qY^xo*ER3qv-8b3p{VYN^8D3M zcw@e)VOIa&hOj|P-qJUx5U4X}&SGCvtJSRD3VZQJU-`2N&l09_N4qZ@CL7Mjp`JAR z-klptq60yYbTQf!wvu%*4^&AJf*y8BzlOG`ThZ{-rlelyP-Ba56kq@g|CTXbVK zHuQlR@aXW6JYg8xRaIIbyeLVFi%KI_(g}gzf-mUh5}JnJf_h*t{f%}Vys_^6ONuIrRBbZo=>{qaR~T-tYQF(s z0Z4r=MLU4Zv&|EuEVI{PUCG?t(CyoY?D%-@#NbF}|3nMNR%T-zl_oWbyF;r`P+Kd* zSRsi%a00Uv5^NhL^KQymxYTCB9j4rVQLj=`Qo(Et?JsNP;Bc_m_1>UgXCD1sh5_tU zD^r4RueBc;aBc+a@dF!-!u9N}SV9#iEwMjtKwdn_7oqy8ut8lcG!pyqt}%&)EdY%C zQ#*)qjK{8m`Oqg>mbGOLikpEga1tI6B6r|~A0gV@F9yp(?6-~IvLYgf1;;?*)ZrQa zJ{47-+))HXT3#cFO5D!WGi>z>+K*SE1FneA93nhpdlhV=TnV`qo~#%At}uYVeME=y zda|J7Fwfd?8((d=dc}tN<eRQ|l{-XB+0s>jrmN?lA4o;Go^frXO zXBiQEr0**x^Wkr5dWrWEh@g#Ioh8f}Utd$NRxRg$2%`UDSYdq3r3;nUd~U|e_1d_G z*y5FI4SRyfpPvLJwBdVzx;GF*!e7l~lSDVYf(8dg9r&}IDhv3DD>Pk?IAUR^cwCkx zZFCcZerUgaN$FiY7ZAzZ*%gG8sx+QQnH+hcDIhZ=s9eAQnCOX;hzLM`bzIbC0lO~h zNoiNn6x;kaffBmmNG~ryUj4ECQX5;;4TpC4Vu^x5Kz}-^ zHI8a{ml+UnRaEf=iR02`3Y(8h%OD-O!A>5x(^6V(ZgvPRQ*AehQcKS}IN=fkeGDTU zjq>c9{rz+TCc{SoN?K|-ZMPAO0{{lXE-(H#Y-+D06o`vh2qU(wzKKalA;2k=tJJ(2 z@ZFxcq<4PC2`Ualdt3UqOdz)Ym7Y?f=R;A%971qRr9B@%KOB>rnHFv&9_v03LYNY{%xUywv)iVct`izeT(rZry;BPGZ_L5;!q!4ks^Jt5(J z-Ed!6rX-EEp)iAxQ?YCk%U!TUh9+eGf*7uf7~PG6r9s|doNZa)woRZ%i~dK10J4M{ zG5R|u1GdM(D>q|A!@^wD-@+dsLK_}CDEs3Xcmcj)1Tr?`5jc#Gd#wK9oXEs9j(G^5 z$(}w*bQVr2bftT&`Q&C(t;@YRSP{VPPKw3nj`gk~I*Eru9&F6Ya>Ue}C{hw;x5P?1&q z`2Nw^$w^aT2w5!eK0Yhl6o2^c=W2VL)HwH(FvVP+;~uNOm|JA+b-rm<>H8yS23B%8 z>{wLBK?{|&2WFZ`67(5!{DYo|q&+lo+W8@0KlOFcU?9|4FDp~roLl5M!)EDHVzlZ+&^pX?ezb`*%U;ic=uQfXXss+=iGfi63 z&mudPu<1<@N+^WTnS3W;C&$UMbgiYb+ax2=AK?5!iT^4K$fkL!TL?}M5&@_nhQwPC zgU=PK0KPG^m4hA4`ttCvR*e3ss8XUpH8p}n4pNKQzFMYMK0eL2V!CSE433QtQDE@< zXJp($3;J79l3Q3fASlPrRo_IauG!}vkGc?9=0u@prse5*8=sUyRA(_s zVVp`@Ub;P>&mB=?CJrBL#Jus-6nRQ2vfp3yWV6AQad`rj(Aox{yK;I|fjYqS6Xc0X zgv6%-gh*VaWSOfMZ$EL`EYcabKLpzMN}PnuJ}NfVwc@xn7iO@J=$C@sF@PX&BXlXs zdy#5VADPdJF#}Ig79l1HV}M65riTgJ7bf6*3L7gSS7<$waCHwGkd1K3^!)BEa-0-qaq{_3@t9})!KGsX=T1}dt~~9mud7l9F!xDSJ-;-#*roB7%<$(k)tZwr*56;64A7V(T<$?hn z-9$$nB&PLgzwdj$H7G#)BLZwpif;BCAoIs;wcnUsxnwt>Y-16_?R<^EkpIXB7a5Co z47zZmLz!Ingffv;2pjhAU+52sBL|fKr(Y+h7|dI>}TQuUDA7 z?90m$3daBzL89_fCl8v5($9g;DyR?wN@@(BIn01xMx?(XTKW0IrSdsBqt4+9@kz_0 ziMVkYLh8BuKAxZjoHe%TA6ZPGqa!mx*xRP4s`oOu@6$4K|zRQ?WcL~C2yusO$nK4lI+Px~`R8uFE8$RMD#Wcg4)S5#EkF4xjr!U1m6 zT1%al<64dM8To=B3b!7#f6IklA-?r^K%~_lnC;PFdPl+U2t4y&zU*H`Dv*=Ln&>3Q zlAY_g(FacbplgG-{#-!uEbS#`D3hSK+N7ePBdeyS2HH7Fl&hV@-j0V3WMP}yWt8k^ zTdMcw*6yoMt3y4+IXODcW5RX4LtSNY{__}HWaa$v_JHR}MimDiZ33n&q$Z8M=|y6V zvsy+Feih(B&2+Abe0oPE!_Z4KRD(`FqJl?NmoUM$KU61WlZquB4+=$EpU2>vm8Ez& z0d;B;4>7_7y8IUVJ#P9d6?Rwxa*ygMj6AhZdbdzcDMDFaJ1@7QB06S5fmSg?K}&Mr zPnmGmxwz#|EskQe=1-6*SDn5BZ@067m^6i^y&+Ec`tu3t>DDp4ZY(vH$Sdhv+?!z< z@5pgW{45AQw*`R(hax%wp!Z>KmW1I%r@866ZyteYZzEDkrx$@&U?M~R-pG7E=ovQ4 z)uvbp&aaY^q26;yk@g3mDi2>=Une}-Q)%#MVM>h%gWWKpL|ogkMjP-uWt zT)lme()CKSY|CXBZ^_x)AC48-7}bi=FqV1_5pS=9q_}~URdLarrfC!H9FcU?;{uv( z6AB?hB4cKhWp~(U&%+nMsJ#mo`592q;AVHH?4c6?pHxXU%z#Abv_@!OBgplIyuSj=*W_z zRl(-!^nG#D_qiINtl@3V4SchEc`+)apayI(7gzVboQvRRCpK479tUx2(Nai4+Sb@W zD{bs=pq%08?;S6(;E-(P!QUPNRzArwH`Hi>q1etod5-d;T0yM=)GjkYy10MhoiSQVP^ z+B^bKnn?ch=HTTziyu4D+_0i~M$apYo%fYo$IW{L_m>w2Ptg7zR)TBy)T)bkzNDmO zfuGWZ9e@#@gLxowY*L6^O|3MPA7fB(RC8HM50dy1s{QE?FDimk*)Am z)z!Vc{Y7`7vX>sz{fB7FJN}YY_`X!0;{}y|k)TvcR5t|xf*Q@ZtS;4C{#-;ksH7rG zD|_>sWM<9A@pu(=HnZobfKk~bA+kmP<432lOx}EWsXBNueHlNe2SI^Ob3sp?u9Hkb z8Jn+a_-l^qU;-@-4MXRy{t9{}NO3+9r;3?(WVZ1PR)$dWBOFpEydQu6M08g$ZsFjd z!hLJTF;jCyo-6z*S;0_7UuT==Tx2~(Wo z^~r<~+;Uh=vvyW>xX$m!X68e66T=G&z@5gRzNlLFNz~4lvSN>#7Q}e93n7lG#Hm+8 z@R(O7qq@HHcNND+Z1fFCSmOX^NL`OJi)q}6w_dcO+j>#GzZC@-LN1Mw6{Kz$R{l5S z-^GY4mKSFL_7!{?@ttJsFh7ZMb`d-%pRu&FAYiyMrp2V+8kOo$Jk=`kuUV=k+TS-T z6g*}EFx&u#y?aA;`0EhoE9@J~82)0wz1SY?rS;4*EI)T&aBf{4lvOjBkGpZzKpy5I8>xUyd#Cf3b@`$1!I}8ya6<9r3=(U#{h4+$iwtE$vzo6uQg}Gw}hG9z^oBWE7bv42c z;fk`VgRvhIg^l(F#oX8GAJ+v9k2qezs|+o2O0J5 zIs1@Uu)!{&$XzZvIw+!@d^~HIPw*j*PIwz{;GKIJ;xf&=z#YI>;3yNmuFq@SJfBoK zZFW3dKR@3=x&5sz3M(wm>@Cl?Fxjgx)VbV2O=86n90Ud|_euNeYhAZt8qwcUCH@}{ zNxeE&9{=8?`q;k99K{d!Lcb$tmNx*@29SDA01RGfER6$iwNY%g@`XR^IowO|@AWQT zGKBm_ZK{A7VNS<3QcufzEt7_gJ9e_kjz_ZCs@rRq8=3gB=wk$ZdPmF6!4U}RkeAmy(w`7Kk&7QT?Fvx%Xi$!DJy~#C)N_v;H&0_T z>h=Cn=p93nlS=}o0I7~@{nn=K@jZFugY_4S zoA`K0qKmsrwau#fKCv%$z7!c&Ijn!z!-GH{+u_N{PUp+{4gjE2V}`dkN%|i09C$wg zP}D)THw(Z86$6YPb;38l+kCPb^Kn9AuqV{gDZ|TyN7*L-dG+kA{wv%ie}yaTFZ#lz zb}Ou|t_ycvk7-E?-YTTrH;Mt-pJQFy2rP*!pRStl)c)j=|7)Jy(hD=a31h@%qIdBt}Iy!V4#`0TVT!@5bSzGImq;8 z37425YKIUj4#K{e+Qm{A1Ee^FDr>|j5lu*s$s{njvJ4;p%5u9C)Xrdx*;U@o3r;P< z#Y>!YNQF+5^Q7Rz)bw;dn;>3_kDref_WbB?}c7Exy6leQf4^RBJ-iHKl zrf3rDssmf5kO28N$~lJ!>7#`q`*)g<>ebcNaSwsYgyDk6s+^C^x(VK&;aGGn5bwZ4va2#IGjKi>FswzG#EuPnr4wD@98O-YiP+9SZb+E!8zRHB>%99 zE0Zcl2wPFX3}DC{av6M~)A?W7olaBzVt!vn#D2}UU8xWMN$T~hv9Yl`sw$BZBeu?Q z+h?T1mZI?1+Y_$aDT1JzF}|o{ej`d}!(#Nie=VoWJ&hsn`N_cu|b#-|=I0fk+XpN|g^k;6#8SSJGX-PY3=8;{pGDN8FWqnShoVs3wk{IAiUQY*yC6-Oe! zD{03Kn=ZW%64@@dhi6x^(8{NZy!}<;oQwXGYcC-T`Zc2|$Up=1=>h-(4Xp0!8^DBL zuPUvLf4YgK(Z|GjZ8C zIHgh(?6lP6kmGmWa?oESpYi%_aitHJ6FC@R2Ydv;i}2zj5Ye=61b@0n^Pz=J38-~?n%9*n0L_$^OqbNIb_5E2o&0xj?*RS-}$ z622*ysCFUeITAK@IrlNH`U|IwPA@JNyPvJlEL7-7Sy&XK?G%Nek2n!S;W;Y9Qxw>( zw%7Q=33m9-EvTyKD~U24o4_?E9MMY(r4(0H#R5r~qqvBREpnxC{O@$M&;51b+Q+4V z^ufw=os81`cLc1^_PAjGCPS?00rmKQn^RCrijIIUuaZ!%*;$_h?ZL>IczYS${8u?4 zVA7_7wZ8&o2ylVMviRL)D!u@o9Dt^r{D+pMRK$RHAUJLCVe#m((F zIT^RcVlum%iK*~*x>HF8fkMJv>r;c%>EW~uaFwfDxU&=hSNn&$w-or+mSu4YzyoFh zPi7);`vTigmLWf8$FeZ-5=wc3|3cuub(nd~G)!@*w_epUDN_HMdW}CSR=%LZP?{6j zw?58yBN`Se9}DPWe{U-*i_Fd@6}PcV#I;9N^x;V)LhF@-&lP98ApE_8!hS46lb~Z= zTDBN#Z@HwZqBbAbRQ^j@#=Lep)e7HwCIq2MKAXoW%LqTl3Lj9W?~7)Kby-q|_HLZo zm5VWE$LKJ_J0q^IHyWzCge+d}&pxUF5u4p)5Sb)$pg)k-gdWSidJ=W-1;$Jr+1weF5 zR7*c$L?#XFT&V&A4hM2ye{k$w8KyT(L|$p&L?SysdBaxR4>KF85zAHuwI#7XM{s1Sy& z+J*T_n>%Z^g~QL{eBYgl@;M`CD@gl_J%o1dPd_aur*CYwO16)Pii`;V&z3v=0j07M Wl3awTGX<<527QxMkf;Bm>q`SLY8WHJkq`O;MKpLb$q#LB+8=m)h|61!` z9u@Z9XP=mv`@U+z6yzi@P>E3?2*UUvDXIiPuznB(6N`)p{{3*iRs&AJI4Vg9L*=8S zJKz_@Ptp>i(BspethU0h;0TJHq^2VTq2WILg@IDi2*E)lrw_7XNK42#C~PkWW3HYK z5jlxzIEmO=TN~RrK_U*u22RFCl&JQ>yUDIVm*%+2 zcuV6x?(MIKGYR-2ZCFUjRyQ;>f;9N`W)9?N82HX~3**6Ka?-$Uw@@0N%4|M|-Itsq zSA5phSGa#!KI|?{pb>?Fp_d*2RT5d;N`qg`t5DJY^}Swxx3&6;JyW&QdL z*Xn(R`J9-+m+aCqWc&AXJ>z^#6S7|-o4Aw?aL_k-h^a??@c3bOL@&u$(`6)uy>;X2 zWaCBa;Yx?Vzr!Uu_mOIP!UCli@7}$eYx8Un)9ki<+mZ7F1%Zc^ez>}+sp+muM?Q(! ze`I9DIFUiS@9*Eg)hj-?;PtSvDN%dK()5%yA<;w&iU3U0p;(1PwaU)~t$}g#~SRc=(lN_6j(0a=E*yJ*S!J z;(diSEJGHKdc=P$Iwh7?SJ1iMeTS6sx%qR=%=5<0*&qM;`Kwh{Oj zCnq*;r)@vu;e=^-*e%kjs{XjRE6Xwb0|>h2WSZ5e*ZwLeTmQAsPH8u4)`bg@#HEzqE%bDtm@*cu41%xAX`$S1QHG1QjmReeJK}b zaK7m6_4WHGSWdSer(v5ccG3s_2&UnX%FKH_3#^Abi!WC<`EBn_d=}}XR@c{28%(U3 zZ?nkTr4V1g_E?rBOe}^Cw$V?2e#m4c)#7q6xBEt$c5%8yo#EzjOW^Tscw+9k&&~7t zct2Lt(WxSM=befC0w&z}Z{OBB{o%GJ3$Yk=SRPb)T=qYoZH-0T*;}98-(Kd*XYxaS zpFbm~@wi6Yw&->EkWCiKBSHJW>(J=sCXO+DaS19cq-NA^uXyii`z7zTH-cbfk%fgtw4=SfecZF-ftG`J%^uMe>}?i)6diLZFQgt1m{hin3+EAvh`7X zsJ)YiYooi{C$CGjR^P)p76mxH*MS9EWhb-B!~HLuHtsm5iF?>Cre-p6=4`!*S2h*X zGSDmWe!7a3?P?>GHqjz@CG9!)=Z%hAa^oYH%br+WU0uhgr`?nC0{RW#QxBQU| zJ`#cZbKLNV2t_R|T2#05ZAE7EKzaV_A2Qqj4i>I=tTWPklabDA=#Dn{;L`L|gV7N+ zf>ACcg-z!VA5a7q0~|BiEfXXY3JXo!(yI>70~_~LmCK8c58*QTbP4QdQeY#{&M2<- zPyX*>&hOdExc-V{JM!Lt^tb8k-mNmd2EIOF=%^YJt!bw8h!R1wc|c^YZZPYjyfuF;R+5o!$$fzi4gFMAnUH30nVYFoXZD+?$089QV`{o7& zuguu5jD_Jd%#M(fhY(7{Lvux9365fT>M?MzS`3fIlsKKA)`Ufsbu6NlSX1Nc^~lK& zoUnu=%rYxMsdsug(t@~9XYxvlc8z#k>lFfdH2Runl#jSTR&_UahdqeIdxyf!Y z#`9(jB90+g`6#UQrj))Y>r5|tS z#;iYG_g%FlHc3MhBP=rV$IfJ-;>VAXE546ppw9P4k#K%56EuBX+&#t_c>C+i>q?y# zm*bO@t}4U+*o=&52JL#nTTJcxA6Y_y-{Wh{#$T3dH(=VfUEo*O)V#A_7j5^0I;V=2 zPeyr;D7m=id=ToxQx9q{%HpHWEL31~b8?RRDSRQQy1M#Tt+{f4qM&I-5%;ZLlK300 zY6h8D*bn|sl~eKHklysivzn2z!J?gRvy1QWsEO9J02!2O)?DosD;K6X_q;==y1}$& zCS=y{gdRM8*P63eU~#uhfLc7lZHSU*;2Lf51rjW2oVQZw7%Kj_hL&ZD3O zGe3A6ro4AX`BU=FQvwMkEs&H@4Eu1g2@bTlmTpLJtRiMAGrX38>D%4i4NpMU44#>E zLn>%e=B13Z6aVhL_ljX19UVt(GWa}aN)Z&IP^rPQCy()x($XSVSM}rLWBgeTL4Yd6eFW^BZ?<}(l7y}i9j{NCK{4>y)Zrly8H zAsB9FBb?Xsd%_R*N4{Wa0#;65(9xllsFlG&Y}UV@D=I495nqC~Z%b;u2Ipw1d0{pt zu?5DDG!&EUyZyR{k2icr$Bo9lS=d}|)_1$0(<1UY$yI56SqXhHadD0Tq8*n+!F0J$ zo2BNkMNqXnGYj+bC|Ou=T#uH6yYxHvDmoZXhgAoNLWJC#>|YhOw0QPZAa!$LR?I|) zXkon~Rg8KTFWfDz#4(y1BNa{S*Ea&kv_4vH>^4w{u8V~wjxf9$S^EAiutyZeW~K2D zTNtP8!t|2m_?y4U7A@urd{)Y&zg@64wj;0h5urC>t%N%sgzrUv;Xi@x_#e-sMK9+ArD) zi6Zra1{DqMHQ(zuZ$3@reZW8RbaT_+9QsE1-odEuXx3y=$-w%HB?=sb_l>OolIjWk z78N0zo11evZDT)yjGUa84Y4bAJ5ZHDq&-3&1P3$jsCXu{v&YuNu8adKUCKUv> zEH~I@_VRuhd`+%TreN{?@2S|?)!A0zm`$ZrC1>V^iBQFj8f2?O;9BK&t15@q_BCB~ zFU)+I`{z2}WbJz#?bEk1BzT=#9tf%Ue*5Pn9C*=4Le_mpGS^m92)~|pWUY#42ld6t z7c%;x_jFEA<8h})*M34OTQ{k(XY!Q_uMBKzn~v0kVIv!kOH4$fprD9PND$8dzJIa1 z*u?tqaBDlU?!B)2@VuY#b#{N9b7OicQZK7*?pNveIAbd!g2T*Kk*Xy32U9Otr``Dt z5o@2Tvojva3bs6KSh?W--8)@|AB?hWy6ZofIx&#F*YrYgjMzp+qkw3=lq#M@;fGA% zkj}S|2=K)R7=F)CFnf~|Cg?1yA{hO{N#I*r7YW}THtu>fzh$||TSNUKY?45@4Q;B| z9nTZbq^fQf$rkCEZD!gGM5Vo4=t-KISr!L41z($1T7E=^R-?R$xV{)%ThIK+qrMMG z>=0|{^^OX*{_T^V-0_AsSD?5!GELx6eJFFhHygX!WrpTl5QwAIe9doG$*WI zApQNhDr7XYp4+1i+rPf!Ibs@h7I^rK9|v4BkPs1Jp`6@YdjO5b(F^~Mq*C$nl130P z^)Yqa!G;)IA&@uXO@Xos7h(YTMF4=$f+cv`DWHWKfYKp8?EdHqZrHlG+~#@4DuauI zqoAY|@aK;azqh@;{r0bHI0{$i37X(u-;-b2B2~_NY9-+W<%Dn93p^I;txZyulL7n+ zd?TA8xtz*sin;7{CVO>ztFDP`(fl#2joApsau!xDi5Vu9)3y&VhgU~TdhMjp6QdZs z1r@3rO#S1NehNddjs^w?*ZK<_7aV*5T_EJLqa^p-e>Wa&L8@FJ)5W>s6*w>;>2=ae zFfjOzafZ&SIEM87gcW*gO(!#YM@?nhn$^zM=+B?C{ev3t1^wvlHTe58Iqp)=W9K#02ZN@x*y@h!`*_cJdU|TN z){OutShn}=KPZyo9%f^!_Tm1P>fJlV)0(AlJUV8>K6FuW@pUk)pQED@q4WLuua{?+ zE52u}2z#hEI7%XBswlV2I;z4dkaq8g$pY`KZ{BO3Io8G0hab_UaJ#mJ-Igo9tFJ3M z+j%J+`(SzFd~k&r7GR+nzU;m^9qv~L3y^iHWJCaGG@8W6Zm|~J^Svuf!WKr9n`+e5 z9y{}|0n!!h;Nrhy{f84T_%6bYNYm)SM5j>ffi3#wMp<@%ou|X&pA0~#*tJ>Y1igR7 z#Fd1vc}Kg$H<~CUZVvn2YtoIs7XmR>VTxhJa~#}+#QEq88Bv|bnYQ|mtS`1(IEb{@ z1J-i%k7pia(uO8B8mh`xUz+}MwXUu@jzaDGTY^BN+_W}pFRlq4n>k`cFIKmHf=T2U zyqUQ_*V@Rx_xMt}K#VoW#ihAe5igK~$h8-DJ&MY(rseobyNg;bZIyGh992(G4`L>n zzFYP@S_3%v&Km-Z1{Qkt`n3U=w3uTuBFo?M6!8QTj9+{uvNbj~K0(+A+}p%wa&i*J zkD~17c(b!5y>2U^db!HX*T!e9#l^)MO%AWkGqcp0+XB){pDC?;j)~bC3q>cI$Z}P; zWUE-!^SMUQ)YSYO7S`nthg505Azrim@9N6!&(>D1^}-M%_BW~E@Nm=#+Ho$uE_ZkL zb5t8-{K|IWiWNj92u!UK?^2B_VV0bQ23y0)0$DZOub`@W&U(wp%S(88aA$bzzV%4K z$cG%zoI7rIOTY|yTAV-e$$hUk6URGzeXZuJ#r`mUEEkdlPrv>`c+`4^DRAv^wA|L3 z`7~Pr`O;{1dJAnZXM+h$`T8{iXm8t~G5HPUzlK(i*Lt|@R{eTaPf@PqL`w2-8D#~aJ5?`rUGHjhR~Q=6>^dLqHvi`v{cu=3Ts?J3NV%f2$hT!E+f$FZ|~H)VsRh6$pzW z-0vlZ=!U*{JD6??e0U@AH55^0rA)ij+Me*fN(Grr0~)@#grH{x>uZJ1JxeA__TlEy ztK0r20I=9akEo$CK8F44DfqlteyFQ$%~|aAp?8h`+LmSj5-d>2HtL5p`^Lg{VH+MS z6ax+jQ5nV(mOQ&3dQNMVK8L~*jJiPW93qol?FR4Bv^FqRu6FNMq*J!s;54AKl=bCZ zj>vXjegm!Vq5%V@9R5~}ofC{oGbI%ri36u=E0;p_U3C8oLST$!b zn@UKg94Pt4G3rPahPztqckr8g`-|K=g#YK2kcKI_PfAjjEqT`IzkTu8Hd z_d?wFlcpMO`9DALzGHLTX3bM1h?t0KNB+A$%Dw%G0!(SJn%!emveh_4%BC${vII`? z>wQTy4W~U+AEE_uHV*j#AZAvXj1Uic(hq;?4nmo37x1}rGcqyJiX!ndx=Iw%su9CQ&ySgk` zT1KXp+n(R(+|me!%p3+LtF@IBF>te@XtAxL{RS0C6T)K|d}44IjkizgM7`}w^y1=2 ztCjYpeIF?)RINIT*Ks+_PSxt%%GQN3(2zX;a zm%bo)p`oFnBBQBq2 z9wXkDORj2YW`csy!$pO!W~+eJ9CMA^_wa=b^~$%x^W)>=_-N(kgzGRkU`R%otKo=S z715jp-zG4ngl* zvsFFSyz+JC%!D{s79{nSi|0OMlBR=Wa#iL!kDF46OB!bJ)beHh-S6WLPmTnynHKSZ zvq@7<)Tg_H)=f#TDHvi<>2jdu1t3SGQ`ld=xgns4?8evs2axuv+nJfsFzU5OR#q~5 zU9E*a35z}t*QTwvhb>9$miRzqeAQrK_LEdvD$a>Xt|g#z`^BAe-_b&r`OM7QiH~V6 zc>d#o*Ly5FFRI5#%j>lj6*H1u7-qpei4b81!%Co4SP%uy#Gr59&s-=L&;@Dr z9fyXdCb(`)&^guov0b3V;9aa$?R#-*T8ueRhSF0_-`yQ~ZvduGE6H&6T&+2-fN*kS zgDHF`RHLruBl#k@7Bor&5g3)CEbB?U+22mRKT#o{zS*I=VFK*&b}AE!DG>%kJH{PS zBVCy7hQkESt94Yt0!Z9y2z!KwyzyPsB^>0AC|FRG#;$>C$R$_6ynleBk=C=nP6A&S zxi(oayXVe{nZ2+d*tcdbV;+{5s=_PmUW2vEaFYwGA>x$$mWyLgF^p%VH?ghdz2bM- z2}E^B$8z+FYIgBcOa`?Nhq;H3W+sUjf?+a=c z-1b5P6S>co!NUti&FY{I0z$&ixe_s_7)=2GX93!7XK&vXO~#WoZ2{B)e?T(~07ZcO zq!SrmynnAbMfs<`an%GxTtWh{i8Ll&+&40vKyIqETND1+;)2oLw}~syYfvh(yrR_b z;p-bOZmy<}H(bfU_wl+R4Cw;q0RZK?Zfgk4=!UMuWzH`tJsu3yZrDHFc9e2UA92S4 z(7;>S7&OUZJ-+l`hauwf{_ZX|J>B{*KPVPI(|HnoJC!`PJeXd-eA!t|4|E6p`XOs^ zaYR@+IEFr3Zh47{*`DcX)#q61l1LcDLEw|A&_xwA*I2*=fBm{I#zm$a4j4n~pYy|| z79kBu%U~=&qcu1`pnYk0Rd$!N{>QQy%@km2`cYlijnrusmsEL-QkFZ#=Q&|^MyHWG zPWk>l5mf1Q?ZAu<_ibn{K(p5D89u#6=j~FXeXizJS0K^`U<`fac3sc=Wm7rU0EUN$ z07eXTP262Q9M46uBJdfm1ZDsQ8RLW+Eup)K7vK`n3f;CVafHHKQ2UNgbv}M%c01PB^#Sgn z$K@eLg7I|-ZUg=(n5wHgJ1AIKSWf$M&p>BVC{{`0vj24OHm1N>%~#9h{H|voyecpO z=0PjQhb+BD=^wRqnq3Zt3JMBN9U3jc8JC0KCl69mQle|z&bvnHi&Wx~u}(;x8NdV^ z)3%l|&leji@vp>FpCpHunEb9vm&Roe>*M3&5*!g8-c8|qXHbW*w@nVe`jCjNwNngp z|6WPyJKkvRF<;RQyR#^+Gb%v1{~>~uMGy`kg8%=&bZ7ti;e=!d*qudaRAi*nKxJV{ z-kQ)T%_}sG;Xi-=NMhDCd;`-~yUli3^cV<1B`t{)bd4~qPTLAWAtA63uug%;HYhJL zGCV9IBm{G$UO1T?EMUJ5Um%xm@z;i#P!zYR^ce{W-TN_<?!ExT=CEc0=56NAN@gFzHbLXGOaSJnW1rndA3aH7%eznh-zVz(h0xbH-2~A2W>4deg~R@Ro#~n)b2VkEO8>uEfFLI}X>Hj>tEfObJD5K+$7HcJ zaEZp8C(3ptUJlN1I4TxqM(F>;R{P2WTkvNn%HNiw5}h04xde|7{1D$RpAchdo4JGO z1avmyx_X*o%@0;1&6j{oSVUpw7Iv9i6KX19nsQjB@O0L=3?hD<({5UIl9tDFa5i=; zlTfZbR#~fv{6zmS*|<1YP-T5Q)m)-5Kp3y8(!P`#V---_t+d~&2IWWk3)xjX@4UT- z9q(2So^P?qDXQJ=E=qu-yCFeC0`g;@ z3?>hI2FCdP#g;Pq2RU*hr4NS*!6(!GT@ebPvyUwvT(<0D)oKM#5fms`hUQx_pa7Gs z6pY%0!;+8M^ZQm9+(O&oT{B{{NP$ZB-9sB*j|ipm_bkPh<7%f;Sa4Abb?t_+6xqk- zAoGohVX}XX^TbGNtKyO!7v^zM*a^nj(jAO6#Vls9B57}Md(GG7^-@f-*&S-wqa)$= zil40ys2?wn&+uQcIj&p5zn>ea=i(;Kg8lPLy|N6MVC@ZZD88W0x4f^^@>&>#q@#zR6U>;$2O zOuf9=jZg|7eVEFxZ)86Kf<919Kim#{#+L$GWeKuUQlFL<7d602KRtC&D^}qs3a0JR zOOYVEjIQ^imd}76t_HJL!0!6g*v-RZy*n5!&R;%*H;jbSCJTfRa*Q2eR)K(~(P;N# z+51ul>ihD7!s{5uH-?g4tMfa6e-vivy48Npv&hLT#;E4eMJ+(^nZj_)1kC(LfB)py z(n6X%VtlFm>LJBy;wVIrpa8Z8l)`2nkT0G1^3^N&%fltlETYwB_s@u*U|O8_`s5Sl zo1N*ryuDw;(SDP1b92jb-kZ7FOw2gSb*Z|wnHf%Ykups5j?>HSZ$^=dsr zZR5@EJYCX4@yCkUKx0jiV>k)k25nUoFc(m{fr1GOUM*kgZPQ*;ECvb3lQNo9rwnCD z#E^Ss4*~g4pHz9kT2x0(Ed(@NV!&ubLEnJ{r#Rn(&_Z5*ezx!9!#Nv?6x|h|J=6GL zK3ZKolgw+P{;@6(V6tbv$_WVV8aXj=b=b<%!llVxjQ%MdXe`mXQr|FhU#~IgdJ_(<%i}NMplGNIV+*B zFIYPVehMU;!D$I+*SE?WY1+R4@q!P-ZzKu9 zV|?N^bIv|jwG``#sX1cCWov*h8yU=uLO3A@K`&8XvAGr}14Y6@4=U8biN9Fan5f=% z5X8ZU8*RVG1S9zE*5#hN9WJDzX_YzOij*L_F({(0z-j*8d#v=<9)WT>P^M8niQTt; z0GFRBTPAsE`Y%IP&^7j9*c;vk334H>U>K+SYil!!sBQ{%#$0zvmgN088`yp1R4jS5H*9QZxZ<>+nuFF4sKc(bq$C7wdv4FAX=-==9Rr0a=qSQ zKbEhtp)j>xkX!Nb<|E6=NLE5p^95opqr-qP`r&ruq)Z*7!}Iv~h(8?8>VOYD%imkg zWB&0&udm^9a|*txBsKXk=yuWGCx{z=8MpZZaFYsuWgfeuENzzCaFEa&@Hg_oH=XSc zP<`g+@at>49Lmu7Jl2tlqNa{ak(i(_cOPV{_lOv5vHG|1ZERiG^XWH@ZMR%Ovjw-; zZS_omqM_Q7Hb&i#5njI8C*F?sDO-GJr-ScxUb#6Y^_;%RajpA2!2^ogbr?eNeii{6qGn- zAyV-FjS=CDI62B~sCvzqB;UZS11Y>we))424_t@RqfOb;h|Y90T9g38HoYW$d+{>e z0kPzJijMVFjWd=w_>iqheFibS0dBuO^9S60`(~=X3W6jwbhMRLI!m<*?$=)uWI1nJ7Z<;ixyts;zA9y2nI60i zlyjBM_-d|;k|RXiSzXQ2LO{GZQx30?D<)Nf+mPEm%eKNk*rKxd@bJ*OusdDy4nVEc zo^oJ|1LXIvW3H58%zSUAtkqwc_FE%>)6=auqJeCFo12>^zR>_NQ!z8gc4Poe;O_2D z)PVlJsxO)>0u=L;*&5TazE<}$eal5sJ?{&=C&1NucRGwuu+5A?K|l}+s^)rG!*X{d z5$msNW9f(?W{g{a>(>UpP~BaCY+B`~Uep@q8Fc*`lab>mL!ON-UQcu`q4ECy-W{&i z^+@;pXk{fwH_u5;S2r4f#iy)RPft(5)^mXWSUi@Omvby9!Q0J!=U378j~FDAOi#va z4q|$%O9#qwa=Oa}YIgWMyB&Q1bqEI{R9K{&s=@8$5tG)*$L|HI-(X}ue0Y|=ka7sR z*e8Gj3E9lB$$jta;gOIwz&FLQw_jYC(G3U$Y_PDwnWM#I0R}}sfb35aZ-fC#jv~9i zh_G-e$5APJnOdpF3y0hNnlbvJ>KSzJ&2Q@Z%!J3&>U#5}0DzJs2KujH=6vT>nGRxa z)6b9;E~((Qn>s5kUqFJSk7_3SjcWZn6$s|BJ+pk{G6>r*mZNGeBTI-)%E2Oq_%J@eJ-|ilusL+ z$j;5A^L<W(ty zYWGN#b)Fv-H^$~l#D?NTATAP$e%z6ye3D zFGFMn`7^%cgx6l4!hO(Yvv6zjCAZc?d622oi;Ni`jQmh6i1KBn`L~nw;Q^0TcPCZm ztE@zdWq!AXx0yoYBhuT?E*ez@`X9OAA?Nk6GO;9)v#vqu4|l&G_ys|=men8E*4+tz zG*gEui<}jvAaFQTlQywdMqN#R+~hgn9{|~8^uU;kHqi7}sYn6!udAVG-Ega+&F#!V+ z6BUJ@vN*vG2fkg;!U72zK7A*Ujv`Dm+z|%{2cgbk6GFr%D-INeU|ecB2pbEFRjgPg z2Lz$bK-Gml8%bp=6<@6x&P)tNRj!`y938~~8=Q)r9S^GXzIE}sJL#8{m*;FTAq<%f zjs5jY0myl>Mj9FkVxVB3jBu_97EZ2#;1@C~YB#{E#t8+WwQT_B|Bk((X3esqt?wx0 zD(l>=W@Jsy>KgTKx1{3J!`(IHN6zQ53j7#$7MFq^qwg$!0(Zx7K#D+xp4gPh&m;r& zv@c)2n4IP>eqRT9p}waCSVQJVMrt@SxEJ{Cu#?+xIrT*rOvEiIod6*J9Ww>XoCGRI zwJMexBI3^0iw4!NXK87v;0kyd;ks=e+3FR#ttUX55jHY<)$Dr2c-mq#h=WeV0uTKv z)8>r0E+egxV$b5Eu= z@^ku^D1Xf()*l&4uf%(XgR>s{Mo|@=jQhEEgH2tNs$m$Is#!oJ-Cl0vS%IJ0yLcL6 zATnv?vh7}YG&VPfFZRVy#IRe=K+sb_354v5nQ^BmH#a-3zuF2!-AeNvE{EtUDnSbWDU&x`O%K+^JRm96r6+o{ zH=EeHh57ka;4BF77y!-7_wGbu(2_AyuFw$tHas+BCFSeo#Y;j)#^CTZj*N)N{DePL zDt~AeQMwhNJNtsb0Wra6u;Sh4j|-IY78Z4`xq!Jp!>(dyh0A3gp&j`3NaR# z!|0TNQ4t9SP$EB_#WwoCdiek6!W^5VbXo9>&*DS80#BE+DXFR0XL5*Brv;=Onrh>| zq@uFc9cs_s&8|8Wmt+_0-XY@m;_@9O`mV0)9=wvw1mbcaZ`0H6efuQb*(%^sP%!Nf zFxx1wyX??(^izSj}O1?e$XWs5CH;%g5c3fIM6{=s!fUZxxWdU z7$d3yp2MfrPJfeBhbSUeM8MI-9v|+jzyL=Qv!mvUN39!^@p(K4dFw6!eTc2+b6%f> zaR+PT_}XVSFNl?b^=Qu7{T-#M`V~KbSA|)OkA9<{?!M=I)tWl2GxA^y?(|0 zlj}n`Wm*Y})uc}fyrS&)#nKc?3!-55jai2|r`tT$c&e=_-O5eli5a#3c>55`d-LTW z&q34d;db+r_Wwx$OeYISY{5ZO4-E4WD>yTs zXVNU0?Dd!}_O0=kzbG!NYZSD!!t*i-J{btI;dAT-OQnw>nbP&x%3uFq^rf+BP^@9*&wnDT1zud0rgcr(1$98D8=P1?z1zMcC@%` z1~a?khXzK4dbW@3{XCVto4lLOl9!!%yi}%4c8)K_+9JDP@N2G=$*Kpq2Br zKl5tLwr2IP9R=?uV%ymTT8w9WdMn-?&OFAMm?!Tn9?~2WTbjfEjPhj!UI%LD1{hbZ zieef`5m=Gq22jsZpZW0W{25?+iv*Fn)nnY0wufVaoiR&Uf46IHzEg72dYze)Gd<3} zdqJ3*1nW%{;Y_8y7Tr!dS-%pLDek|&&hmvfx_Aked80uaGHN9~oMqF=nGv9yNo*@Z zXoHo$QQaLmcSpV$4#wS`ouZ(YMkY|(9%IAkw)8wTCO(Sy=BD2%6!(hMdd?)o1s7Sz z-x;e|!+_{@K198}?tpi;DBwTT&(++&Z_0fT zXtuWjqyDX=_tv8gQ~hwcgw;2C6bUjSe;}GdlH@9bK_|P!4+knX!!ykOGI#B~quVfa z%C%P6RleL5ShL;AfdqO@Vd93sx5@=b1Z~*SN3o+Q1jru&?EO_`C=p>0O(8IvSy)g23zh42jJ5z;Ia>M; z_t~?qOve&UHuH%fP9T5fzkIa*O(;;E#^T0ZY`u!6DEWd9i?7btjtgGj}-**mMTVjOl*@5M2oSVgf4HtSOMgA;iUn^YsOreZUuz4&!w?NWJ&U zAJ|PvZ01UV-q6-qCTD7fE7%u>PQjlhMJ+VN!hsd|ju5@h$E;3^wE@V^EiC6hS;wX{ z-l`6+hLp^)TJ=sKVMd7uUY~7kfcR!VXrEs)Gi_(podYO$J0V1P_|N4R9(?B>eCUX9 zKnE7<=%%8fK?d8CkkQeD{wK2GD^E-AiIHU|6cQVY4GC&!5U#JUTXEy;|H*PNWOl%+pVD^F}Cdg_WcL;-K zVWC(M{|G|-7N*f8qHTb#^ZuJN%t=Wq6Oqe9{FFKr8^;c05Rg0v+kK{g7NM@8@0V1x zTO^LZM$W;+SPjg{%ggIy;o7*QB;xwjC~zo(#V48{Nx9nsQ(B@GR%s%N4ZkL7ln47? zV*H<`YDTIuk2JuH4ua52+jw|HM4HqQc)wnvz_0ya?~IRseh%6T5L!wmD(nylC75j% zxk_g1o)x~fS!{#>JHCKLAh|pSwr*h%gQori;;@`S2aTl{1ZQ9%AR`lj#PbOVlEFg! zk9Usy3k_I;oBVA60uBrhv!0+1EHF7=Ovguu;APUx5e!wzkL6hWQ-lb865wU4dWMS!j|N~bWQIx&&fc7)`4$_wWDJCK$?yf zVCMm+q2{FS6>9vY{Y-+U4Q_STuu`-0$q~HB+A8Jr{LcnDI`et>$I-Sd1y7AuJ++UY z14^g<+jJ*M1jWm-i8>e)eS|F^Q5!7}S9hBZ%vRL-FePRSI*g-7)iPj=_Ut?rt74Oy^2^=3S!XV5i)6g*W2bX@_Cp$$YgeVfN zI$e@UBZU$2_00>N<%?h-L)RTzj4a{Tah6OZ{lQd>YwK{zeH9x#`up4);Vd`R;aU+A z<~?y5eFTxt_fpq2V&tHeQO{;<8PnSCGp1{D6YavjNFz)>#_A@cLd5Wk_!#0D9Bk*T zDD-bju2TWAK0xe)ISOGiDN8Vp6ruu4pFn5O61U8p^&OnuAxp5*E7z`Ag$J+YRfTcB zV#D*B;kd(4y>0ZSkN)Zu=DPXlmi;0lwcBLt7{0FR%q;J{rcmQmm}!djOG9|>gtv%$ zhj;pazc}wF!c)Faxv5blr;gx>>?@tfY`b1HLY_1SCPCT)G=z7T9ZzRZ&4gv1tZBB? zN>rYq>0b?#SXF046&@}f`S6^U#>j8I9lqF6JR4`w+f$D_z?%*EWP0@xvmo#b-LbE? zR;OzIkGQpL{XeKOF{q-Ven^B(u%Q`8$l~RGF{x-i-UWP2NYEctgg*|+l0I}47~r(L z>%aa#p>Ul8c!YDKNaGBA?(VetahH!`GSZ~&s*!0p35ml?tg?wMTEX_|_ak?zTdU`| zU|Y3UWQxGnA|A`?7&)-CRPwtamq7-ejfZh80 zH|K*OWwY}UW@gU8FJs8T)fXLEy8AW}sZ&+~4&Dz$D>cUTMlu}_KVrn@hNa@vrG^N zvX>Lil?}yw>m+Tz$8NJEp?nYORN>L0Vz%Q-mTjMFB^n;peCt zO%Yzt;HQ0?VV8JoFdiHH%YyIt{0=NOpX8$z+<$y+wR*NQ9mb_FYC{(@MaMV%8xzOR ze9H9?zZrHXXiJik1(fEnwAQkcflvDkuc$8;gY(MCdzlHj0Ttt=X7?F`eV2w8EtYm) zeIKwKuGTND7HR3>s1i4>CH2lNH>3Uclzw)PET;QYgw_RBX!)-RtO(v+wTzvCl6G*`Vk@+Aw@R!Bw4D5gL{T5UQ=mMb~0 z=O?#QZPIG3nBBA6JZ$?<)qn*5u4S5^D0jPK=ybtim2Dn@_K>}% zy}{Crqdq^_N|e7P%hdq0$ol=QUqRlp?zM9O7T@~Y*}%~lflP%9XK2&C9V;vA6H#jE z?*H+lb7iGN%YK&4OST*JOeeinVB2Z-&->)R-zbSoVMyP760Ji3S_cUrRMm7pfp8pY zn(1Bt+kW;ZP+Mnk@+zfI=WFY%adXL8 z8gfqdi<o?rAhoJL`luQekOm~Bg;D=5~NJxgWBXmM+---1V6`wu1FRC>lBAKv#1LU6iCJt5*>f$~7$to!)CoU<83_YdL zfXY<;_Ac$cBQtQYiD&by20N%M{klB?CJqGNG7BrKwcI6vo|ivh%~~=s=2~#Du$5Nx zEHY_a&%l1RLgJU>ZWviR3lBh`a(leLJQ<*hIkw64It|McEH`;!wA|``2QSq4$JH5Nz@IkyqK=O% zTjAqXmVu2N*|6+^2EyvSV8@D8wCArZA;>Q>5*r$py`7)2;3>ES+8e+llI6vb-z`9t zN9YQeBX&T(+y^5HF3*uQ05sj+&C?SOdN_&kT|H=6c?#?Ae}@@OdyfmY@CkzmRcuO% zh3kPM*gehVvQL=8X=~${LG|+G>cK%&4FAnQ`Bt6^ts-!TfZp{9Oe3*1sviUVW(2upg6Nr+MnHlkd$=p+>9QJ3vAhHTS+r?M>uMyK91N1R`MA zGhG7AreyU;p}C1yal6a}(G(>`MV-KrV(2p^t_L}5PMbwRH8p&jMP|m>ECm|+karjY zz__Q^tcC}(;%lodLuo8PTrJAs>F zqpT&nf!!yM9o39zhNV=O1t6Z*H`_9f8jlN$b|T9UA$7-3GNoQb=@2q|ya6*%o)Go- z8%k|t(+_O$iRL=&q|L>KTg~B(7B7r8}UE~hf+HK zS9Kyb$Gw`lkez%)CIkdYL8Jsh5NQ-pIwTYk=}t)r1*AJf zNknRRaX-PpqIwhn;K)M9s?A!N!&b;4z-O zSEhri(ERM{S7sTKikB0OnO^)7S3zfL=j3z_DbT6FM-5#*XUB$L;Q@v>?WI&|6X?<+ zfz>vKC(?4Xhz>Z_P=9|+y#`MzDA-#-l+F;>y>g%AP4sk6Ww($0g!-YA+XeiJpoPDv zw)#vA^Pv*!jZp;`O_Ix^tv~+0nyHc;EU^7o$K?%U;~-#|0g3y`-l$>SWNXMph!Y3} zpzdp??Fo*TV9@vdXbWrRxd1#Zfu^P=$Wm~T&2M*!=TQGtaBvfd-g9$uDKJF|IPC3-3RS9r)5{0S{(y7*IN`mU-^_ua42LhIQ` zE1IT(0hL=-&=>u2awFgrn3?sfXm7h^(yEXbDYdoyda(#;rsAsUlm#JBpxC;52%%zIqM z(mA)S`&x!(+O;a~HO8K(Ge>%8NZqN~7vWA7G5+*ow6g2gG5%Mc3uhw~27T{%v0#B< z1&u9&=vLY^pPe3v-}0H-+V18~2h%Djq`Jtb%&Hr?#7%?e)}YYQvl5*a*X<71oso zZ#~>Kp9X>@k%=;SDs{RCN%$=z7EDc@MW!|-TCibH513N+1_L_h%M|Y^$3%gP7`dzXJ@C-q>9TSm_yb=z^ z>euvhyuhwrzJP-Y_IJ6j7mScpGx4O{FkLi*^p6*{VfgfIqW&^3d$e*yA|LCQ_9si7 zXU1ZsDiSdA?j1&I?iwmnJu;>ukmU-hO2DsWah7mZb>VRkJiWz(Eq;Oc98+9NU(aPR zu_DfP$L;wR9JicrK2Bt@Nxh_B&TJp!!cXeB=l4%&V##uKWb-y_36^nQuAwy~vpVM+OjEL0nYkA8gZ9n(veAxE#v#tlN%Jfplf2I$?Yd}OC;Zu0ajM18;Q8`E=j z=Xt!;jW-^P5g5sP&oGd8XC1Zx7BnL90(EY*R0a5xeq6#AyA$olc=sHA#Op6}sc+^N zbF#+XMfY`2{I&5|t9~Ep*6|DrNwO?F_k8ATG7_hGP$t5{=V7x6r>Lu7f6r9E$FP}! zb9J&#v{>pDg+YFs@BBFwH%}XsBK|%!n%`Kc7b>7mi5#{|d+k2EaG3`gE!LBoIbF2Odc4)KAMTp-2r&&1 zuX{G7=K0)e!kaF3PjhEEu~q?a$)2;Sv6qV9mfpO-ji{Z7eh|IlqEunD9{>~;7je&H z3!+^!j^rX2Vzas0F>^-k((_+V{u(`EHg`T~*$lr8IHcMkn>=2|3_#3UtvzuvefLre zzFD0I&&7Vu^6F?^|61lnR!)nfhqEHo8NUdywz^o{6>Civ2(|_CuW|GR`PVFo&9-{}LO0SbcTq5gU5MlI>&HNyWtvbO$lpJ@+ z+@(dI@;A);(E96!;Wj3oZB|}6+>=io6blM&%2NL$824KJAMi#xg|@@AYtpG1=As`O zO+TDJAK!j4IdYoaTNO*m?N4f*8ZjlM=6yF{FxdK7hM%&GyyzJXUA<R13P~ zi50QxWbsUukg+kXpw0^f1aF6+v!xX<1TEyWW*&=PT9Aytrtj=4;}CLQ`^huzyT#PK zK3N6(k@52}XjBZ#d)IhUU%*+Ls=0Xe>Q(+&L6_fpAHR?ws7|yt{JGaR^pkqWOHFW5 za^=yZM_~N~ea+q7>p#3fZwgKa!;4T;OF&c+^igmSlxWg*MV$e7#Kdx_e-e7fOFbCK z+}zyH@sHOpp-B&Dxk`HZG9Ch4lOHIk!A0#hj%;rDoY6paB?HV4GS7COi;D~GpQ5=+ z)}yD%^~XeEKPJv_Pm{i9GAT=AQ>3?(3A0^lolYM$h_X!MZC$VqnKLjUd**-R7r%Ht zb$SSO_i!*F|7DL+t;gYMvP@R3zK$6!D$Xw6K2dZoE502?wyvUc6g2JR@&}3kgUK|-TI@i zOMkB0W9x?uFr#|heLz$`@j{wBHtNyT2&(8@^?VKYRU8EN^}H$t5QLf;L^2Op>iOPN z)A;1|+`vZAB+xSNJ8)wmX{@0jg(a6!R?8nwdq?m8^Y7X3+Kt_TD$9PUXJVQ~dauQ- zvu_*<3JdG5fib)Pn+$!3?fA%iQ zD3iZ^^X9_#P}cC?>G4Jwd=V@g%CF7%D{bIufImJ?7W0x;CT}}~APw0@_!cb#i1-M& z8Tj%g_18utZO85u{o5196J{&@>2fv0Cd%uIacM?lIy}3akD$?(M@||7sUK2z@3NaV zP-ve~wDoeG{YKW`zA(KxFU$ftRT2QvHW$7?o(ybL^jUufABh`(ea9=)y9#agJ8s(< z{q~<;M*z=#Ma(l8Hn93S$bUe9k+zvAKks|0`UYQ&^u9-NogSAQn8yv0Cdxl)6zPS4 zR?Fne8)li<;djs{n1!0<-ou_or(%%0B1W6~`9^LP{aIY=^XvG(ohd80Dxg#04>p)t zX!I{?L{6Q{Vrv@}M^6B?bV)2u2vxjd> z=aoQ*?5D@o0Z7xF=jrax{+~eNm+SssSa<=_R~0@6|QFFRHSVUlw)e1KR^GQf)tvV>O%?2z^GHzfbd~ z<2ZG*Zqp)q`uhDTl32L~p#PSF7C?Ax2RMM<@1vLqO0*1mE^F&mheElJlS$5+*E|ol z8JU{Ey658nw@O$nE2wZylw5_&1zXT8D7$IXd&$GX5AVB`&QBua;j6~AY z(|N&23br8{$WaiuT+AtF&-8_oACqHECMGqNzronV(z|Zoy$;EnrY7b=`UllI0dtLAJ-Y-{;%}*G_I! zZ?S^2UqyCFg@vDa&-*|?m1tp%@ObRo1az35_xFV+OhCEBY5Kvi75{twTN_7zC+Yw` za}s(SZeI2NvvR%O(WL#Aq@p4bTE8M%jozXShd&6?=gR@@-uPg~hDOI_^g&}u6q$u* zt_@`47Z`<*u?DZ&=qh+*qve^Q<%}R;54-~&k}C4Fu4xP_?#Exdx-g@B7zX?MNg*l= z_h0c2Jzar!MT#GUaGqc=fO~O&e;=o|EbHW;@k|ClLoByX!z3SEKeVuRUjcmh0`S@c zTsu^@0l%Z6%ci(;rAV{#b4Iqf&yOJI+dhCR!OWA^zYARt_c+S2@o~vah(Uu&`DIg+ zM5Q!(F#8Z$5+5J`UuYHZgQU4Rivb9#1IjftG~8#xGl!R!*Vk=FPH6ZnePLBk1;6Y7 zntF8q(FYCI?MGI`^kTHhKBqO&aEbZByPn%`4~-pUo4Cu0*q71_nETG29vLmIcaE2= z0s5+7=Wqr+r6Q)iV^sEB4}4#`k9nUELs#_E50JT-iP1}vWL)HFFKUCfxKio%aD(;n z*Z5nmE17XTcC!*;G1>=3geERddZ1if2<(DIlw-?tx%UIX_3PI~z|Z@uoT=&LErVHj zT=V9&d-p+4!2s$<*p|58ZcoDb=c=J!gUU>3>F5XtAm}H->pm)xD)Bk6Dg`d5E4fQ4E*;M3D@;0h_8tFzI}Uf$f|;`z~~4*gjd$1 zfVxwhg;1oiN`nL&wv-FZQoie#hDeM6_=#l$| z2(!P!VBpdzzxU~)Wd3Yj!`Z3F7LW`q9oCCWOQEpR1IBW1Nf!0U(qw_dCL$t2SAW>Z z2!EGS$(_@4}1s{=y{vb}-7d2lcqRey8~CxbbXo(uw1a0lScpPUt=0{~liP8Jt#6_38k{MLv3DH1^bg5oQS;3EV+oJ<*R@IEJy@F5O@;@HlaVJbwXC{5QgNZ>z&4Q8!D5|)_WXe z94j^+{}%4==#aA+%nJX4r+xe#md-lQqcXme+Kq<6umZ1n zLN;H#FaqNiPB#&<(Rd~XvL7Zw8jv|bE0+*WMe#2#epc~JR|Mx?Oj1HZ!nBLHxHznU zqyf0Z?XWO?10wMio$!d!Cs>z_AzR2Dc91)FF6V0&%Yyu{=lvNlGntATpyE`So*3%`8E$jut$_dzLBKtRAUVTUh%ef!y(27~kXUJ? zgP`jW8YYYCE%?tO#ZNE8ekW^Wl)|S#E)$?XgG#h#n*-c;G+4=HJDzxfE9?+lv^{Jc zpw!Rk12zi>8Jn26(vFEZ|DO7nk2?ObgJB&$ zZm)snfyeQ_?cw2}5inrpadW_5jvR}@HtP6m=sc34{{`NAbYW3>?=s^>2~_e;q2A_Z z$%p)JeuMWAl`Fgxe9nT*!rBjBD(+WY$G|k9H!G>y$Lh{n`w-hQBdOZu=doh~3D|7|eY!_vmyrrdwby6+-Xu=6*o2l4tJ=!mr zRmW3HRrrnB_gCh|%PiB6FLO9T*06I`oPCj~gf~hBUvGZikccOF;!vkgM|?-%X}1pd zy>!_hJ*p(bZ1cvS6o}#?j$Am^?g_$H=>>y4%2RlFTqafl+-S;k=}| z>-kh`VS3gzt9QNJ>~v4;NelKc2d+#@yd9lp^K{vAB|%E11_b$6jrtdPZi}bkuOsJ< zcKW|`+)lH=qA?XHkxQ?>doOq6oP@6|_R}xa3v#ae{P-W@W9|}Wbi4f+*D^I_CXZn` z!_8(KIB#Bb>v`N=BbpSpevH%l{Ip)>$5wqy!C~PtV;fbxIhw=@g_HD;4Y+VZ`xshH z|JL)0KKomXGk!nWE0UdXo1@69xT>{vmIsljlvlN!NWNb2xzqN5L*u>&OJ!^I2cKwt z+?5=sKPqmSLdTM<^vgD9V&hY|&)F&`&yx+NjOCm; zQ>Ko6`<~56+k^1f%*uKS2R{EVifSx)IrAw^L1KHeHrcFha;u}5Z}&x{CqM01pYUNJ zJYt8E@lVTd2CBb){Z_%)tUMwBXJTdeS+nEPQg&^FV^BA_hBMi>T=6L9L`mvF7T7nn+0J_VpmEkDnI{uT`UpBzWJt}Fpitbem)6SK8)M?Bybdx{)1oKj@DF!I z5R%NgiD9Rvw(NM>RjDdHBS@IZRJKH zmv@HN8$3HNap5Nh3CEKwJ#nNA>fuD28`)n35-RY|HjcGPVpiNyk0nYo@t8$I=S9kr-C1ipA6Nt~QTc zM1K--D|(+BjTh|ZomZ&r?`!)44_~~^-{(Hcp^Y*$jYLWm$0X0y3G4+538i$sSP7pk z>0wolRI*saekg2hiGJl^*!h9!m+|j-SCNOB>RmBW6nl93!furBm$t(nkVwNS6y*Mp z^AqjF$>)Qj+3yT$Zo*A8_V?SmIBqjzblaj=SLyi&*WB*WLF!kx8jA`2oO-~^L zuAsXC=6W+~HNs6_vx)7WC=!p5Y3p6_T@uzNRtpi9crXE?a!`S3&71#%{#vG+<~dT~ zCKb>=wLrntLVa7c*`=54_2O10S^<3{kC8toNs^+Gzb6)_X1=r&_G-p$nGV!JS8v=n zf3Ptl2bhT0tcyJ0iGjD^nT`n1X%J9B1qBA;8*=eFWR9K#u%t3kUe0$%Na%B4-y`nG zt9M^E!QbDwaYJua+H{($WWQ(M;X|0_A`6#k50L9nl|n&tl$DFV@=peF{)PS_C_I2b z@2EF#{D+3r>UW_M0N2Bd-6QZly=k|duA{1~th94FJa=n>G%^wznuc%8lmF2Igh4naCX)E!0~%k*xYO_K{V!|` zY!~-FP$FPjTg_~ASPb1g0$#&%q<{)FZ#5J(Fp{e(2Rzr;-d=&uj?q!g0ydDOwNh#q zv4(msUr_&prXdASfi! zXn!CXP*LQUT`2fv0U*bMe*R&x8XK?EFSQ#zV7Z8bz*+P#pG`m=ZM3Xt;3_NK_6p%l zEy0Vrj6tUU%LEE!?)MH}Y|MQPWXct5h#MsysXgVpeID|jWGo?}HVqI(LeFhzJmJX-iQ}HpO~9uaj!~pc zZc*%$(=p~X=^H@@5O{$(pk=F_*Qudq+640oBQvwigdM@^iSP2G=PM(HG(d9UgR-G+ zci;i^{dinM!}fD|0grfGWj7#~ffyEJK#A@xkia!|o=m-xNGVn6-UnsK#d{6$1;7G7 z?g7pOACOA)6(4@nPLd2r#%gPmaW4RG<`o+o8wj`|^ziT)%2Qtr3_oFclw{+m2O57} z7G*)6<0m{5XUK&l?DSR88?x-M9rDFt;S!2p%jQ|DOz0V1_?&VC?9 zwEs1f>%g7J8Y*&CLYiU{BMHJzfJ8F3B~{*AMfj=1rvty4QlSuarN02y#s5mc9hCPpVME1Oy&qun>aa)oQdT99Ab-(j*Ht=7EA7D>Ea2 zzeoL7aK&Kp(Bi$j+t_X_LK8 zjA)e@VE{8G8$o*`bNIAaw~EX606m}{DcSB?h}x|? zJ3TI`s_FnbXq+*G4ePsy-)N!k_4d}*pML?jK1jB;v1tXXN2qR`wGUtl7q}GoR0y}n0{;2tCxZOrGgvLOAhMs2nh+?S z7X<|zyX%vbkXZqQWajj_%8wuKIyjW=ZjL}mLJPd65QF2oy>LD)EscbNA`q@08dpXg z-ae~k*etTt`ymVxV_#hnrEc1}J`K|HOQfWv=wrHz)`I{~ezsE z+VK6*VbJ^Jcpjk4XIR6>*h0EOl(ev2=a!uG-Vb7-&|e(%F8DW6f`a67cOcCUdw*lb z@TpnD^JSumN?QVWpCQI)^NJqkkVpI{waQL!9}!xvO;D?A-s|arre` z%q{vOIXKS}_gzAQZrVk%7)du5?}^}B%*=s>VLxSlBA_hNQkCBQJl8^!BX#nXjltPh zO+Va}g52RYgC}@g zhvO$55~fYq3h+NC)Y%ucg2RKtNw!WAx8IzFD2UmWSMMk&C~znrL1=pra8yh}LhlPh zbAa9hpIIA(ZowFiIea&-MF?Ta?1Q+H(tAm;z_IT0q3)giwebL8mhL|aW=W&0!`yb6!y#-8-r9vQpEU%iA{N@n>K-qq}b^Zz4vPoacZ- z@)!!YtB&`%9+f(hYnioJr|vfQgi*_E^DC<{3rYNLSJt*OrBE{4K)8EWl-Jp=McVr3 zOz_l1j#%m;cg5LMMKGkK{|~>IP3)+w((N&RRF8XV6OyVw^w8*8X5N>UZaa@uG|xOM z?bEs?t;XDTT1L}#h==1REgi`7=i0leXzZQmBr+-Q`s%tv-LWO4KkV11l(3%;W~p~M zUYioa#k)B+>Je!Dx~slNz3PPR_zwdkBLTK=nymg$={`l=X8x5cdf%s%26J(y^b$!u zk1&3{O0wR?=sZWC8xxoGf+axy6yG?|i_q1TxMhA`lH@zJJ*UcRj_*r(y52EfUL>Ti z&tXc;ZH&58Mtjatkw@ zoKL-DS(8g`^K)zq3o1)LcUctlDukQROGul3L6pqz+}Y~7s^B$@qoF~V@>N5sQ=L)l zi0X={_p2q_$-5-jFGNF{iUlkD>hvT?7?8_RM;GeVt?-=tcA{?-7^}}dOccgha@q90 zuHbTduHy^&h-^1LvOM!N;9NG7y^zSTkzQjv_gt9wm7g_R2ah$!j;bb8mfL5HEtp#> zOM5o|Bn5S9Jo) zZZ9TXIqW;iQQ^+#6>mIclYQD~c$M(GRs#DIF@FW)o8q>@TzTv76OuE#E%In5$|w`F zN^HLlthQ{tAQMK>e*9CfKOdB0b&rCB^DGcc)5uTWYZTQ7RFPi`I2KH^nE08`!4_gy zv`QpLV?8z@INNRi-I!vJZm8lHqi7Wlt@Uu5UyhCGjgJgN(UfDyw+$HbrHK5=X*I{D zeUfCQD{=6C8qm+^g~Yr(`tYSrmq}8T!u#gx0$gCqcX4 zzsN?2Ueq;GQhFy@Px+PIa+m#ZLG2pjphJIk7NOXNK0UY^^(@EFW+aH~RJt!!*enJs z_O&cTiSKpotVhL_o=M)E7Ts-K_;b6mAh2gA$cIn1o?4@%>dn=g{FGmR$ zxvh@KXx|!H@}`ZV*Q;|=c`{@wa(2vHxBnOl{D!DE@vEBL!t>3J@dai<>-x#PUu!r-L(CJAKk7_A~Bd z`yOOuWol99`{JIj{?y!j^YC<;rNXApi$e}=b|I{Q!e==zU4a9KvJyM>$&55_IuI%(NaKmWC=PO1AO$r+!D=&->b z!nUxKEZw^H@luQvJdUHuXpSfE`{_2@w@;*1_QZGfX$kZ5*X5kZe@YBo)SN;}{ym*o zh`@f;ts3w0J*_K?OpJM1atI-A*xl0*$iTmiLr9H;F2P&yGAH$~|3_>)du3|Nuty2v+@aL?iM78Tjs63Wk{-ouxL#0OD zpWu8E{#?_jsIH6{oQe# z(TJHcW1}>l&GCs6R;vAYj_q|ho2)!qEQ$GS=?YtGTf_b;G;%N8CeqRfim(`;D>ES`71-7L8Dr1TijbVHEpIV0-E2q^Ve4IYEA``h~YwYbPZ$n8E=T0&>-wAW0C>p z;f8+U;kKpOeZ9Ty>DMDuUR)UA*RQ#hJ2k22)LqQBhf%t`&x2fJWb+@-_T~JNRVmDe zd>$ynFpcAQJ3(mFvL{C|gzgnm>%LCw-%rZSpULz)s#Mk~^ zrZclxG5w%y3MAs6p~HuU5gCIn#(f@|+P-K>0_~MHNOA7YXn<1=P4@nC9z+c9fb{?c z3ul8UMI~(@XJgH3OmMJ46O%81;1)T!UMy=7!%By9(puL98M4Fq8jbo-5= zkaY#Y0H?|_^IuYWek*cl(#-z+sg=hhvs7>ZJdiQS*3mW)FNhjp!UPKOP@MxrftYVC zde4X71_8%eqJo8m#mY|V-Jn@Wz5tL_U0r>zg;RS5_9V;cI>DDjbfLszhaeL)HIXY>S10+c}D&AkNGW-E|DrI1Vu9W3-}z>P60YjEnYj%x%03YE0*^$x63A)cO| zc57q2d{3t?Lnw(b;ENzoZWzOjGb?)q4YbQQP4VCvUR#4Vvx9z>Q`bK3HM}oINDiTq z!iVjxtt~$Y2uC3z_!!c&oAmVbAcIfEQY=uPUVSXL=yO*#4RYxqIz@2s$s;!k0rB;N z&#~#(c1BN0R*77mKM#N=B)~pj(DAhN^bk7KOr`D6!FNK((AMz;lt1WWhE667*y<_5GF8>TnQv}QozamRI&0d5{X0wWRpSVPfx5|G%yvyaKn&K_25 zAxUDlv-I#}C;6-uTBoIur+wjy$Ysc2xiphh-VJIZSw72e2%IoVErKFq6A&osiOtk0 zmX=m)i$E?_XwJYSDk7k8NRNLg+yG@*DOH#cWHZt2H~zuYl?@1xszd!!F@Vf6>rZ0YM^%Qpc^#U$572RzxFFg4hw~%9PKk9Km z#z}g&r`TkqBP9kB9pi z`t4M=%o!lH1c`#g9Dq_kKt*u~k00di8mt|Wk@gd~Vk;dq?&GFhqg;;L#hZoRrDd5X zxL#0&dG{J#3fu~@KR=lQo;U?*>*}_&x3~Y0dkJY}DJr=V4TWN(l2kOE+{AN z>A&AIoM7^eZ8+bWxOfHfzTn|}^me{G@56VmhQ`l{bh&N?n0SSwIJn%Jp+E> z_{Nq#>A^S6$|gUmg5MNTr8%^(zYPw?0I9%#ekzU9FD=cyj{T<(PK)RD#x{N_wexnz zpesP|5Z6C_y<%e4A`p3FST2fN1rkihKlDc%R=VerT zk-_(J1c+|63}j=8pPBMFA9nIi?Od<)!*BWbrAAbPe|fK_bp=jdC+!alcfkPP{(m28 z8l`qk5@yoA55}d3a?(>`aQ26;*dQnPUyl{e2t{{l{5Q1DNvnO}hl^8oDL97>R26|r z<`^lm>CHfHf2(}J&ObmEd>Ct>;4)Q&_fJ(n4{RF z>Vh>l&YKBig;P`ce820gazVNxZ|p6>O+g#$(SZ5xLL@$s{Z&^ZiVXAa(<>FIHUYhN z8I%O5IuOE)P}_y;%8R!D;Lc)pN$^bL^orrw9NLJBFQovb-Q}auK zw+LO_A&E6OEf@xkGJ>26B~UW%zeQIDh4`E2&YwS`a{{`FgoMQRHIv+9P)r^I1w1=D ziyFC}9!jfmt^TQF9lQh;$UoiVB z-!Vua-jb`0Tg1b5@ZZ%;x)f&9KZOMxz)SFo#Vb@n=n_hmq5E@jG55gW;MKQZX6NSv zKoXG##7(u&nHY=0J73sss6PlfN$Ke&I+80NyFqvmg1ET2z`c?`asf#udbfZiM|Ym; z+FFz((iJ78@Y&EQ;-NZZP9A$9M!23bVi~oPhk@;JXM(wf`8Nrd_}lqmXF5bg{5X}= zFX;Ywr^A!Hs)MH%hUsc%>HP=- z4~0^rw-*@YFc3(|fxXTT9dCn6eC0)by(oI}AX%~tyPiho(t9rVd327~mdC5L@$=g9 z%mb>bua7vcJTiH#Ts+tPb9$U0!I`#YMfv&FrNyOXEF<5;3trD3&6g-9`G2O?VBvZ_ z&fnQ<^lrmGbIXCPAUw8$W8I^kS=ROps}i5ezrCVqLDU%FviygQzPCEY3zZ%*d32WD zrYmNJQ3Cq+64;*t1~w=Vu*v(2BH%6yn@Kh+UG{w2f}HJ@*p{KqGS=krQRI?yfE?V< zz4q(O%=eSU4`;E^=@ITL)}U8~&I~HEVA=WhR}W5lq%lIsSK*pV=^Ym&G|Vpz)d+T~Ena03rGu+lQc)^vCC_HsNEfg)%0wdKfpwEg zTGCf1T~_fa5q8J2TNk-T3EQSFB_B`Y+hk9vC)>Ccvv=Y@cbP6Xp6y-2d(_*Uoz3(* zDLwY3@ObBzn;|h@v2B=-O|9YDr(D})@jhBYXy{`g&1>{2(E3jAJKGMZ6C%P_u$jk< zj4R+h7&El1RE_rFnQZ=!LGXvKY1`0bQ`Zq^t#HA$Z5$^qdC5>HgH!c>?C{X`!GvR# z)I@oyfaZWFc6{A8fr3d5&<4cYG|DVmtZc`#1w1_>P*fd5v957JFMb63>UPZP5jKdc zMZEryLr6j^?B)-m9wKuz!xT8_Z(r$aS%`Ih;G&n+!S51>y)jD#nug|G!!PntkjeeCms;L}M5MVjmTH64FcF+_GtQEB-GXL1&Ke@V-0q`y6=bhePJ6$U<+t7awH$YY^P9(mu^l=$ zUBN_~1uemhtFr6vrsaBR3Pgblz5opLxB|kZxE8Z(InM38pDraDa2OhMyM2C8L_aG3 z5~<^|cBPKQB~0Y0}n5+NnZNeZVn_LT8_(Zbma zQCZ7?M(S!+U~@M+Qv7vK}QxR;r_%!{S7`)E4-#>PK~Pf8T{bG z>0vEx@no}juoUs7I~Zi>Ty*`?EB{RJI=yS?*{Twa{_12)v;51B8#V9jInG!<-M~#J z`PM`6;rluRg7=`SKOuX6=g&7&julN}XAR7xtmSx)xZF8O7gf7&Rp;9`!g%6GN8>JT z_N4sT{7(5q16EXe4?}SeEiAp!Log;l9Rl`mORGL*i1m6A;YJSBUni$8mp|GgQee^KMK` zFNFfd%s;l<(d!PMWjp%Ce2Ni;1R&M313`!e4ypS2X?E_}sl+RmKA#rcI<>;3chm6h z8PSoTrDK|vnal@D3+<5t?Eq-Z02R%lRf5#i_=v|YZm8Y^sDB6pJ~B393a1bfdV18s z%LHl=_A{+z!(s;U$4@i!!#+c|6t*)u=t*#JT!0)J)Xe}%`TZrvcRj(#6l1QR zr^cpN?@r;*Fbk+^VDeMmXCWhxf3HZ9w6e6hxp_#IdafGYg$u1dr#tjeqk**@6Nmu! zCulbq4EW@KVzaihbe|#vx+$RDm;)mTNciWVoHA2c0vOLWELQ$(9Mks_r%uzz$R!{% z+5iDTae_fZLsJL1Ip(oG*c(y%3NpL6XtpV&^#G_-tj)U^K0mfcWZpPnX7Pbp>nP!Z^~C=b6lUG5EK;5WP5I32h0W@ z5m9V|Aq?yR6@j#k4F^E9U=YXr0CjO0sC{b;++133PPxvS zzCRE2;)f*L*d}cM!B8e$ z5{JB|EkLb2wI^9!ETL&X7Z%jg9IOKa14E#~XLF*0p70HGQ`2{}&+-xjhf|B7z7KiU z__q?&H7LdnYy7*fo7=6ISY|U;BDs5T5Z3@!iVz4+9XNmjzkhmqdTpzH$t15JYs9R1 zH&zdKX~ekMK9XMi53hLi0FC^&!)DJFty$OHsNOa&hft4pF*eZZ3aK%^Z0`I81w z;+b5}oA=!2+X-{mhl>sA;a=QvSiplBO1{JSnkL}NQ~3ju=``?hqIwOTN}G`QTNdbK zj(^YR#J){I0esDXZrmp`xIS!fu6Th`%0JL27RL5LK!hEPlK=({7sLhMCZ9TXz#$L- z&TR)#obj_~k)WD}LF^b!1fy5Ful3%jmJ@lp|CnRl?B61K6p#d~Fb0GA`3bq2^7luC z(OaahC|n+bjs7$u((h{CdzcRuiN>CTLVh@}Q5fYF62@n!RLw^bAW)z*#eyYL24-ra zGAwv>OyB@AduuaB)hw}UxAACE>TK8XZ;(6)zl=`~w>Eco`Ph?zIf~7@U?v**17=)!kmUZ0{_U%pHI z6&srs_Y`yiC{+N4HHcr{xo(jp=0y#Z#DDn@iXGnv1P8NK!P;;YB3D5n_Sh_1BEJ6o z0#KxuVy zI-{pt>ntbAa}7QLpf!RA2HJP` z!Hq7w5VjnkT4Xy}*#;W{f^v}{Be(^_Znzdd+D-~Uc(D8^3pu~O{jxGO%tw^nV1Xo- z7TA^dUOIsX0OrF>gW>`;aljix&6&>y<_gratf;66Sq80;JA*R4PdveOf`%U4U>I7u z2(LdlAK(o@=LDC0{Af}v0s6kWo5GlPfJO(khmYVsI2yjCckHa%fE;62n_LE_2dree zI63iqcz=2l)}^@$QXy1i<-YsV4|IlT26LJddXHcL-BkelU_@+#_JVbkY^KWn=7NtO zZ^7AG-fTqka@aKr(CCa!AhH9RbP6@FkcD#wNd{w%ZSitX6p}=!Ks0mnviIr;C;UPC z**lO*mj5Ql-`Q6#?=JeFSVd^LI`R&-)yE(^L1$5;0T1BJDA5El0gf+o1<18fnFJsTQ3n{kSUM6CHo#Ccx3UsK&2MD{Z3VOK zg*}wgyyLOY0r$q-@dRFG)HdO`F--?t25RugvXpx}8Hgj>+75Ko-y}dy2hl6SS6)@W$HB)Y?QcRyJ>3w<@ z0y@U`s{voeAPzpzc*_%gu&?w`r0-iyE2Sn7v~gm`TYt4dKqAi zK#LytT{OAeA1;>Wdm*j@MRcq*^lI?@ePKn3ud}xWuMhN}K@Q9Bp^qHJ$)nF9Og?3= zTKu~^_{bh|FhS-AIY1_Jp99SeM-`Xm^_#NTUbzwsQ2tTh){UQN;_7 zIEQYf!p5-9l49{9^pjxttNgPuU@9Pn>7-?W59E@~uyd=K>RUNM*(vP2hDH~`YH$?~ z6QoCb0~C--H1Vzm)M{a1oL1UUXh*wBzJ2X=BZg`BRnGJs&R$*c0OewVJ^Sf*Ay^paV2efT2y_r>y$A?s&r6a3?TT~ZvXPxO zvG(N|Y$<8=qlXOlGd(ZfbMih8$aVO2N>QNzjxSR1z=M^VrP6v-@fC~+d_R)tfL=JX zB7DH-B?%6~G?m;TnkA^)Ag8})fe)I8WH6WUYf(3B%%O0pADf$Jp%TRY@89dkp4G4_ z(y$kBK#C?QNMc(-z*!1iMf2igX#SPThEvOq>Vgv5(!@kH?Y0NGIxaZ>1DEKiso8{t zgv#EsN8a|kFh+wLgwr!yzm1vxm@$uxmYT2Sus+iR!vhZeZgUyqndYZXaK5m_E8qZs zhHgNIqm8G5=<*UoOpiuk@xXF71fs7_2N(c+S>p7D4lt*lfA>bAB$5QhOV9(vBPLJb`eG7etIJ z!3j^nm#S*{H^IteVs!&Ho={L1TpsdizTJuj&x3v15~dqKy?nbKRgnkA#l<4^3SNoUkkn;?!Io{i+knT!b+sjCp9jD z5{2Wv%l{K0m+x6$zdvCOb7bGj1c>AK#RT}P!`3n^2_!bh6&R@pk~yBot-+LKy^iz= zCg(5wVI!VCrvRLAE8sBrbs1Vj@Cyq}nT*g+xd;D`Gzy9T&s~lG*MIc?>ElB8Z~goJ zv|nb|{^x=0VhVTvJIWmQm6regaMLK;mQ)mrjVQ=SF#r*R+Ea(C7EJWg%BD;??dyKF zDZkusn?h9-`k4N;WQH%GA5MVkXU+SP2w_7;yPM$1FT2+Ot_tR)k-@=_U*l?_Tpp{m zP3X6W5IBeuNY_4UZEugQzTnRgeIybJu3&0tDWH1+OvVgH4WeRV4Xvy7A|uS|+#+yo z)#Rb*ktx)vD6tx5dol+19^C_>qZz}t0h^}UFV)xRfM)IV2pzPiBE z5Iz9LjGBBgWV=gYbOh>HfDX6o@&}hq$gz0;bp!AKI;W5aDo{8FrH$yHP?c=<%h5OY z_9}9xuvvZj@im=~8iEd>cnz3?E;np^gET0i0Q)2s?C`CyMf7wvX4vKyOd@Er>L>ngSZx+&7p!i3j9Dxqco46gqov2$Hy&D zI-xr4G?}o?rG#fX$TdT?&toP{!F=03L`ixDEH`3knK$ zi~2oa%+uzCbup?tfXT$g24Wy)mV+G*(!Sw_(*F!+xA}KYsD=b;GbW%p0DAscAj4%8 zrNDh%$<(j3p#t$N)CvNx=*1hp?HNo|s*TwC=3VlG#b;Rgzf`PYrR8y)sMKeX*nOLq zCxg;7&dCE{R{@`Ggl&q|mVp~a+|sT@e*BCC6}{he4-InRq-r}wIFC#YeK0bgqx72;e^dus3T3Mx!LGK*(j)0%4fuYM zH92W@o%>IbtN%VPM_M_3f9pJSrTdfAcWOozV2yh~cJlYq@v92>L6tS`+6O0V9E@p{ zk|ED9zdXFpBVNji+2+|Qp)tgSF#amvI2WiN{y6SYrh?q(!sosW0bcc*)mi^7f+{N} zW@IdrKv=DY0wa8!h46~*AI$z*dih?Fe|G7|tJ!X1C5v6X^u7c(S7v7ece3{v-s^3j z`&f)YykYF>DT0@#%T)A)?M>!CMb-cPVV#SzLDy&Q_+8~@ZvGT=E4nM<-or<7iUwCc zr$64@_;PovrF747>5Mm}|KtPd=GkQJK~7eYC-LmeW<*HmUAMe&|H7X+T5TB3RgZ-m ztSVHZCM7ZnI?+$<5dp%G8^k8q_{TbeOt@W-&lRoU~ zp4xfFEcCX#S{lF8&O1iMN-Aa(GyKA|kaV%=37)D-|Gg^A3rjuyQ7XJDiF|W@&F{p{ zGIC}yF%;WhtyFtxQDH?Y8&}`v?>x$MM(hgGHgmz|d z=5NgK`XF;M&P%96phzmco@Xp)rrmLvHuKWLcBcJodj0u<2}S>qntM!74f+xWB$lo} z@F}XG({{3-Tvg-9o*!R)lWp5J&+INr4T8FMFY;I#FEGCqP!SJcFFUm;b!QJ&e zp2UWO`Lg-?UnKgz7nfIWez`cmnr zrq4UIoV8!_x~~4YwW*rL+g7S%DT|jOQao9<;8?d|zmM&^>MG^;q2=uli@Ln+^rU4+ z_DA$3y}jT%;_9|=o>uXBCg{v)@mnEZgRCXuH zx%o9K!ml#T7hTa$&kX!N<4izbrKRhC78aGOXOuO5Q}6K}@NM#5NX$;!8r8W}Q*h#D zQBcucuR{mt7+v#u=3_^19Qcqk+f|yS_cWDLTUg)@T_QvG8{1ZvyUVuQhAWRRd>iPw z)5XP6*{!lNMc}?Hu)!4F3hM?MO#qP15J8Abd{}?TFXn3;hH@IeW$s+XUvLwyxSNd35v2)V# z(d$pcGro2Y2ktZH=uCewwDn4PL#3s*dkZ5pxUT)-!a}Q0d6n+6t%H$w-=@65mf2c4 zuh5aAuEktqOM?!FTBi>U)ro#xj}~6|J*NFQ#G*~@uc3T;J|UQ@mv$2}D!YA~?4&dD z(@R5@SXP&RX~NQ z{*pD*Cb36)B-m#&)xbyW!qB#_VYBunlNR2MHZg-kS&E7c4RxFLQ8KwEv^=stIu=b@ za;m$h`!`#umGdcD{2KksFu1s|b8%Rnzj{RvZTI`}k0}}2huv20lQ>)C9Kmj6Q`uGe z%IkDRVa>$gy)@Z{m)4I4r;QmOMH*!Xr1ffUv6Z)88)ACd@g(>#ORMLHZ6XJ(`ZgA< z&zJd-Bg7?O*KR;a-6`#z#TAR5jt#X%!)%fBm9`NY7Q=8<|rz2w<5| zJfG)eXQWfn8T6rTr3{UE$L2%QBX^8OOh41d6qE_dkblYbC3o%>nX87OLgxHqbB zZOP@cr(0q~tSJtQQ7K;M(*?J^I@~M}ekk}!HcdaS;MmN=j*ibWCO*C`?%O%eXBiU2Z8(9*N$8qpw>$GwH`qP@+ zYCU|PHmSL<(Q+&vzc<_AGWOM0|7OXkg5M##ITl9ut>wDlgbstTUMuhXnmr}Ky!xt_ zcYQ1>Z}_4XF5)_tUQ)g2*_5o57uv$~2f&%xbre6J^k4C^F9v6h)#wLXD5^p3*3dh7 z^5n_x%r*N~HLni&PFXgH9C5!|_IGUV*joLF}7u0N+90N=&ROX*xC^bfgKups$ZdJh;)3 zHoAf|B&?KuJ7*>M)LM^9kefU%LcN4VGVm^Q(V)T=yQghYNMukzjAht6X*d%T7vVda zTixV^k-Kpl#WFKxewGnIEY`3}k;b5{qf?F++w3)|+X-4CxpQYgxfL-!CjA-g;E?hL zj>7Qd$@tXNwMbotF;g~u9=&=Hdg`w~ybX)czkQrFf=sOe(zmu0cmRJphN0d(>{SPO^}El)SY|< z^C>AjYJuA_c~ieVR}faE{)_2q6rcj)&kLtV4kW4)as&|8-@hOZwg&B1^X}bW_8f?M z`}+$Y>)wZij`@9{csYS&1pI%|tu}XzE^MB+HfAx5n%SX>?Cioh}ek@n2L= z{)haUd@u+|Ss{*jn4qN)Zy1PWIhyG7_@ty&2pbD3EiI*c=bB2bUwbomw5O-x1tUQw zdF*%BI)3ldH#bR1$-B|j$lZSWbj!H{_~U}mfZb!jk!RkL&UiFx7`nzPKvFgFuGTA$ zj*24vv}rm&SUD8wP7|^>0s^w!M~sNjRQkd10oGz4I4i=XRn^o~0C{Pc*E?ZgKs2Ih zKOmawf!?@r5*Qs1V%%Jd!W|ByZQe`C)fJD_>AL3haq7(*H9T2>h9oy;<;s=hL)7pE z&_YOBxEep3uB@b@c@tGu-b~qZskd_B!W1C2iT9REyl8|lDjo#&v(nO>EwREOLOKM( zaP#xqH+Z-%JSHwgM7#$5%8BRHBS+RA(bZ-89CQ6NW@E9ZdH{<72JHjgV)QBtVmIJZ z<>>FwVxTPn{*qOA!N8epp+bfaQ|89+6Rn+V?7;iLxUB4M#iQfJQ}X`lk!})qSEhOG zwi0t}@s!{uYuh8~m<6jm1o)sX`!#$BFwm|`0S4kA0;EDrOwe;JhSL8_0!cgLJh^@x zEg0Sp7t&I<9_1v%*KQ2nQx+x^3TLtoRn@RFwv<_%;KmVK@hy1yW5C?BwY424=6_k^ zq0&}z7IWwRv@Xe?l!&|fMkL9I?^j!)g9q4RbRBIFv{h0*9c2~$l4H!ugtT*n?hsia zev(V*bZ6%OwX>JSr_j3nuPtm8>DA=jR_MfmpY7?4Rq=apmRpULhwKc7#jn{&bZ{Zy zPeOBH2OR=@uxDgsCm<_{XNYlCYaY z(Hiy)3~Yk|;5m0;A1@Lc&&S8tm~D}{0UhzNLH&`JI2{(GlN%fYH508R@=n}Ki?}Ty zNL+lzivf{>(xLx@jF(SCdq-Uh2E{ey$DMN;yyoP-Vl?`OSdBLNsdbS2j+q#Lo_ zR1>9>iCy2>_ZA{}B>GO>nk4xKCsMMxtxoNE}9B~H?Pn}}L z{5r&E*o5&CFfMMVqR|S3- z=>-r`3ucEnLE;T}+>43|go;6YD#bl@S=h+u91aZUo9gxyvq{xQa9qIjtbI$Cb;YXC zf#`oRb8>N28(aF)dtbxcP)N?@X_Z%#Joe|87P-8W;kdKR(PO6TfUf`T4^Fh}Im~b2 zZVNPMa^VSCh2xj_czJI?YdBf)c+|0W+ikgMvK6{*i4mtlHo?+l<+9kw{`faArY|`7 z$)Jp!2@w$&jfDw*3yaCft-rU`S<2Vp;oI%)rs#55Mcb<^BWo-5n~rP>(-e|-V};Ex zgb=bV`aA9uF&-Q^+wk`_iOWr|cQH2?9v&Y4)6A^n!jjVM(3OH=ngnzKWkP1liN=5S zJ70R1uv9_WtHi5IKZiC#Nls`?hhL&RC`c zt2Lah?ROtIupV|^4ws7y3k!q2{o$T>69*n~!t!Jk&r&GKda>U9ECZ??*5CJ=z5o3} z508rDwv?66z!(Sh(xts9y9o+|o4BL6N|Y?GshYDCnyC~oFYhOslQBW#ATl`N=jCF)C_VTD%b>ulWrq5!Yo{d7BE}!MrD=n~FTU(Q%V(4hQ!C8?jT__V!TRp@yRA49o zi9IdH_M~NGyhSz_aXN!{N-qv%iocTYytZoB^tXQmrEqerKCbv5jt9;ow`DRJ=XCymY*Nyy|fI ziJGtRvVk*v+Y+*~PvFhsV4*ojk|g=y7lY_gifM?FAt@){Hv`rSdm3CvUb<^ z;Ll(t;G1g&@byHy<*1dPBm(ux_$)J3*ag0i+BJ3K9b~2~BzQyJH}M z6@6x|?($o~D=Zv#u8A=$H~nwKCmBZXW%Z#@;xWRMgwwGIv+s?hzsFMzw*> z->(5dbFULW>R|lf`rg$R%E_pOU&DNlRQ!;1b&Og;_6C>63c$-;2+BcDATd^6{xzhG zwNz!iUuL^w-QND>N~^LP^gW;Fc%HST*^TmvIYtOA?d%TrJu-c1O753R8O&S37&uP( zIxCqwH9ync0PZRz(}uJr`zb<)F8@K&?qW93ot?0kiG6W6sgfK^nXI4(Xuw3x%nsbF z4YnU{nX6F8YU5H{SN|qlQp`<;%aykLCj~=zmXxt0#kK$WKV$DwrAJvv%|z~$|KVr! z1+yOE_e^(hxDj1z2Z@ql(dcW4R6L3pGxPnI@)bK1ZAx|@povUTUf3Mu)<0am={M1X z+Di|oEXhdz{P{H68sZK~e6c+|W>{JjA!b>S78DU#`ZNo5j}SRa&zyOt;jN*u(gImD z_OE*MM~4E=CvJmn2@Y?U;im0qKM3tk><)?7`&YL@dwRn&wrjmQROIVn|i3x>`VBR~Ln;;hnCO?&9 z&w-al$-{)WYEo+ACi47VF!c8iTxmG=Sz#@T3Xo*x+--zd1fwOpn$tI1=|Q;#6%Xd5;IW?B?B5c@2h+@$Iw-+v=`0ffP)(QQz-^Z{ty5ou!D-ImVT#grp zAQYqsDdn+S5GkdAhb%D=As};P?Z&#UTFkda(HTRF!^WkkzSMGtWjf%GpOBacGpGoV zO)An44xe9+^Xy#%r2h9HPTbP81mU?+$f?3}qski}dl}B;p59(&_|xD~qD(aXQV;c< zHBLSXC9whJ3oBG;I;j#nce0_V$cJlJmF)TZPTyoj$j$QUxk0k#HyIh3Igk>&8cAV+ zwj9k6@v=cQRRH&!?^hdTSgfp6+{cfV+yWI4T}lH4itCx=xEl z_n6cc2pinVX9fjS2sw-(CgdCoK&ROaLWk(Q;M_@!T@RX8+wIdSM=8d2+11s#nM8eC z(Nj;>)Yn&+F8#>VyiW5fjg5_sG0)i6;mJ*uCP;ApBDn}54t@Hn_FzbmFl#8cppKzBI7oKFpf1!ME=b`h-jGJkgL>h9V_$DCI_nqB z*CzXQz@n)ofGMgt`2PxOE5at+{g@^!DfEseU?rB>V#$? z_3~@%eP^s{5{`?^oY5Ca*3BH>w9MWc6W#zNHlqrcKCLMG%)hdXLsArb&se3< zt;^t1H*F;{r?qA5XT`(otP6p*Pk%IIqr(2KOc5$F;LvEXz>RRHSeu%DBf)9+>z4*~ z;adm_W;Q+?f4tQPYw2srva$y=4&ndji^jRkHEFD(AT`=_f`Ts{4Lxdxn$?Z}0Ag{K ALjV8( literal 0 HcmV?d00001 diff --git a/images/small-tile.png b/images/small-tile.png new file mode 100644 index 0000000000000000000000000000000000000000..ca586d9c51a2540d1a31c169032626992787f9d7 GIT binary patch literal 14347 zcmd73Wn5KJw=cXXK^mkRlr9PBkdiLxmhMKnL_(xQN*Y8&>F)0C?nb)1-pO;$eedsl zyC3d{iyLLnz4l(yImaAh{DV*>1xYkyB4h}H(4?ir-$M{gHTWh#dItX18X4;YFTgmz zmlTBx2T8WUlV?V5mPh%1o)SbDMO5+B27X{JWF!^lSfTPwe5f8c>D#0CZ|%ci zEq|Y3-DxsL`9^(m92{axxcYm`JTq{%Y1p_Pf*9l_!D8y+URAM z4RK|h)02~58~bxr#_eCQTyYy+bXi$h335!WXWsviUO{NNUciP~Y$j>Wp*QhLOOLI4){> z_#U5?m34eJrZ^WTvRy5o%oXIQT^Y|D#5?Njsxionab7sfjK*1`6{jD1vbpWBapF|Q z*x zXQwyyWX&U5O?)Rqlx#Yq6L|EM6R5Cuj*)CYxv6S_tFTHGWasjQx7k)M$?ob5?&@dR z=3SHQ{7FY8d`?6W)57?AdOM8+T(EombivGVPVZg~d+1L(D^8;Ap^3guza^i`)B#gt z+Z@SQ4~?Ee9WSuKhueCHsXR z@5;`)XXfVW=A$C^b5q`BiMY6MauP+9+gx!lRoTu>np~&4EwX7XmKcZhI7N{O%8g3P z$%%`Iz;F_wk$L{3wBRJd!NH+mV;gzJnt;6!+vh6#7ty(__@?iROln?A&sb)!T8?Dr zJaZmL9mD0ntSDFrk5xZBAOQC2>S~_6V#`h|)va&mYgEJl3pG4UT3Q;-uBfQ!FUd|2 z4}9g?%-~6}(}qlpyLJKI+a52iaB?<{85jiWs0hZrqM!f&_JB<~Xr)g7w0(L{x=8Tx zZSUe6g(kO7>LFp|(V_&Gd5xG)@CXya1V9~-&Nzo@LE;t$sE-aHrOwm9k?3b7R#1R|7>nA!@Bm;bl`A;vsO&(4kwMt-oH%5*dse-Du%W9TFMRHLPK5;@kZj(e_J&0ex@?MTyC z0k>n^cVo{StQOcgFgLBorBRxbR@tj=n%`hdFG#H{rznl1!Tcy*pU$hTs8Jsi=1j6x z-E{a92dCJa;Zq;q;L(JzRRvLB0;^;QI%&q(_OI6>n8R6;7+2TVB@+wV>+KHZoOkI$ zKDAl|HQNY0C2N1!i`MoM5erDUB7})vU}Fbxm=8)lrj}Ta(S(!oSN6N(o{uEm8nw^x zPZ9F<%_zWq(8zIY=gqA5s-Kj&wifyCMDRcViR;`}{KZAgt7F6KE2J|DgP8Vr-=(f@ zo%x>!J@t}e+|8O5C&_DNZG#(H!WWkXAqIJp^FNR8h&Vrq`W)^ix_H$1`#Tl&)p#rv z3NUprVkCI~6Z?JkHua?e#rz=)c9wA4@o#2I70+f_nr2z`lhYV|b{O_JS`!(JJU{-< z5U|Y`_~)xHkKX5z&UOyXDKexd$oZ#7rI!yX>92jvUXwsO`u=d|eV4y!DAmW4rt@+B zUrxHH?j5eKjv$`$^&EwY=UZmP$}^RUAMymJpZ-F1>&WyUIA6wt60^5Yc)uj?{N|oIFhd7qxEWcn|w8w%CWj=DT zh56O>U)TS5LjSd$ZAb$*@tBiTlgruae-~=ZH(Na@W($RGr zE!sETb3w}k+)IH)MMWKv)^nB24|k`Ec^=#r!_6i$N1o08Fn_?EYTXX)@P1ENMMp;~ zZ=$cqlWM4{!bAT?vr%eYwv9>)&#aAu?a3KP^;J~^fBvK@bMW)?11bJ3O-y3;{UHCL zX1`+2m~@}{P+FXRf&xD^HG=Tn(dP~)Fgar9t-%U{3or-Gf+ZiXKb)NU+YW6jUE0-# z<n=yuBzL%-?D5T{F0TsuD405 z*66e-$@4@>YYZbUTmG(Vk7&eSO-(V9M;~3OV!yhJ%qyH(dx1|O`~8aF<1M-W_vAw8 z=yXU}*1%fPZq_k4IX{3xs;Lf-goLSp<1RWmRW1Hu0S2;|EvNT$_NS$7k2LPW;*Xqm z6v!)&DM;5Z2{|4ri%sAV-onPle!oBH%V^ThtXqxQ6-CZ^d6CR*-}zfUS&nE@IY%*_ zYnKEh!`C*`uLbUo+K$f70%c6^#n1@}33)#5#LnCt9XSLB2Pbj5tE=NZl|YpHDFZ*f zufi6?6lI*K_>avEZh=98fj{c`QT<~TKdybp@Oky_-I0=I&TzJ*<6VW_!Eq)=n}Ei| zK~tqHNaenCx!R?Uw3l(3dt*C+>x_A9}_0PNrL~>so2-B?&@_1m5cD}}$MfL76 zOVYTo4>Z_SATiA5+-J||=h^n_P}367m}*O{9$=;D!C~08|2ZWAk1*M`5S~oOz|fk# z-&dS3g3n})6I__f*^R@{E!eO^{bHH=MR8VBLdTSoqJ4~uF!{W;=l%9rfqW~;H9y}u z7F{ga57Nc*c}wsH7v$UsGUhwwr6C=esl~h0o~dD>%7^f^{eOql6?u-g@sV3no}GrB zeH#TKnc?xhv?_n*&6;ZlP-#^>rHY(OohURsC|>`0&Ucm8>gSh&K%TBg$8z<;aO<{N zXB#9{?s30#W(D5ZsB@o*QR_C(nw%=>T3Lnp)*QIxEKQu_nMXU3-)GGSBP|4_Z$!SH z`iGFr1W`9toSt6A|0_8_p1t-mx>ku8F`ft%W9MVG{thS#0I5uX75@RD*{I;DEQ{=;b?{CmmjA&i->R-+lxcCuN z6&docT`-dleT!#ntL!|MNoaAOiS~>ebnDIZ&fm-KylJ$G@%9*NZ+)YC^kqi9t!+*C ztz;DAm!oSamk$jF@}So^5~rOL=KFYeX|S?TY??i_HTMbaXf%zpN-*0-tqVVmK{0Oy z0pa?~P_2&Xv92BlB*kA!df)OQx-aa(lJonoOjLr6rI1QHI#u<^CN0`OXBR#^RveVSi=kIg8=~W8M7VnaXx8 zAC=3tvVPkPyGi#qC;K|LLw!_oq4`W(*S+aa`1}ouHWo4RPPRdeKy}t+4eZQ_M!TY(kQ)G4mlnE^9SgX=0+H0cW2(7wX(3+k(;d zXMG1#cr{B+LI+M}bE{sSSE*i>uIlvh)6hJ7K_dr2-j@q*07_twj*jlJTwd(Yu^F`^ z)%DG0h`{A*S0ICH-hzC2+={}gd8cfNUM)l5z}j$zZ8n%f&ul+aiV%j+TIrR;vACk5 zqB78GyDvaSMn=Hv^hzO>F9>{V$+b;hko#U`mLJSkSWh?k34=6aHdTp;PV#ntwgLvK zu%7D7N%#FaBy`)K34>2U5!fxTa2_8mReP4TPm^YRHEMBoIC$pZh_fqg}FSRGDv0u>Ap>!Uo2-VF^Dkz z79Stqc&#(SY)-RJCueL0Oh-yyKF-xQNYoH}X!0V4M!vN-j*&8^2NMS;F!TlOY=iCP z!Ge7J77o?g1vS4Kvrv~IrX?gV9XC_Rcc%^eox z&&s^~;Cg@vek-JU8lYENeUz~*YHbxQ+i$wR&`I9L$HUV`)2VYUaOpK>M$?%q(ky}X zY*;jTSIlj%G2W1WwJ|U^S?P6ofB@ZH%-O4teJszvM5*#%`c}OE0#hvzB++P}>sRC` zu~R#&FPRF{ucBt=>!#BMvh$IQI};lnJwUr!v!!nQCR=#HshQd!EN^^&UVd%U*2?8R z^{=AGT;V&6>QZ7`3;;{>^o;9v-xhej$q_cCpwe%Pqu#kC-D|j&lHVS(;$3#MOrUt|+l3_HUK33wbR z{J*>9d%3%Rm?<^IgolZtRqX6zZ9)~n#3Uz=0`UL?_A@9w9n`f;%$w_LEgxB2tfCbe ztxB83GtZHq5_C*VffPuX5?G3Y=Qx9@{D{gplt{2?o;&o=TLlGl@U|UXeEhZU=$HRS zvJkzJc-nYZS3AN+QIQ~k%%r5H*|f~}z)Rh|y{(|%=+vhfbQqkian2by^1I7g4>R2w zOznFb6en>IZ-zoykweSod>mzy_qt*5p)2ud7L-p;?{NI_J;@u2iiM2T84%& zKqJq}QFyFTThm%LBxLPO2-z*vs?qO%1C35`@$3F%?jfVfg7PI~zFp&F3oW`#%gioJ7jpiptM;qedL#hn8XP$!E6;^6yiwP`x ztv}d|A*d|`qYIpI2s%DKo-WB+PdxyANpvefI3s1|icm8M+L8|~uwjPJz@cg`)T`UG z3IT^_ZMwu*v)X~O_T%m|=&I@QR(PBE8`{R}>1xNUSXU`2q?6Orks4=nsClwLr^N5k zHxeG5$5})~WY~h!V)WN@|L^u;*zhn!5znBb>#cO->0(0&%6?C8i;s!<0n8Q55(-ZF!@^_-hj6LQ|ACI-sp_TjyFt+P_4RuXnGiy=EYJRYP&&^(!wOWl5gT#0<9IUwuPT zw88+}RMGb}_h2uQlz;M{>oQsl5&JUs%a?)6${*}s0EX)S_E+>8yc@k#S#+6%E23I# zdpASM{O2R){a>tKeswZm zVsNqEgON98<*Xz8oc}Hr28j;uQ(0*zHOG&HqJgv6#m4S9MxItClIu88Ek_x22Q@6k z;v=Y8Lqupb@Zj%)`Imu z^ZoefE?^l3MqS1Ww`Nyo3LGJSSiO>g>LuYN^dXz8Hq(8~Ya5;L`8)HDiZW5tQP;^; zO>5(riwex4w6pNrJ|20I%+k7{@ZFN^bZwcotBRM~6Vos`g2k{q4|)`1mYE|K-%{fu zR`Z14x|h?Q{nY7vvXL!dL-Zd$1jy}0cEfO812^Qd2&wd`^JJuglX$+;52e#hkK z8mhTz@GXZW|ZK64*|_7Bs#L;fk76p} zTDR|ixe(oW{H)9&SxV^5ocU!T`BQU1sRZdu@!V%gz#$h>ptF zEclRx1mW!Xc_2lM7!B0%^OPgSagMM`$HTlZu0c)_Ov}lehG_`3sx(2n*IM4bLb_2P zyPU5rj#Dl#G2Qt1BoXt}S$V5vkf-#5SXb8%rDjL3`eYA>KJEBp+gUntxPl^l8D~TS zw_b1bB*;26!Q&D|W(N3Qd-^ zS|lf4F2NUpV4d`5{MxpydBo-t%XN5*2EuP!+#6nQ#~pBZ?XcbFz=jo(N*9e@IJ?oc zr?g$K{#ET8T5+*F{*mQHF1%IVmFW8TeX=Td4Mj07XMz(2`2;KdW7X(xsfUzU|1~{n zPYqvHy=-EF6M~`(as}bm)nSt;rZV+$J#nRrr6B4ywM~>mm|Jr7fdB2i*>ABq98=S` zIXxvpAH8lx)EFTX861iAB`J7uMmGafcK0_H&#?Y{cgKVWS?AkgMS*OyTT*PT-N>sh z{_5!Si?NLj(S(FPtWAr#P^uHVSE@b&_>*mQj*OtA_$?jTRaDl>i`l(V4r$wO`j^o$ zGovA5khxeSH~QTE)Nk;F`~mC7GdYwv}P;kv!v?N)H zr%TnxTqF9zmpPKzZ6q^`#q~b7u1Ep?p!1q**l&8gw~uj1RX|LXGpksP-x2!I451Rd z&gf6AbXi>TK1DM!GCCSpQKY1zf*nZa?uuj7*t07$@V!QeAm;7__-5}Q2lPiW9&&(# zR{1SgqNRaejVzFDGx9TNfEcziG6g^;_k)_PUmE~^@w@y|lwr7DjLpwydPPGcnl&=r z;Pd`HcBSnc%>ox|9(rXfg2-!>qCd$r0Pk=}v$C)ZW^&Dy7$Y{`9`Kj3&+X8z3CL^> z5f%m@rZAGDc%M&bm@Y1q#kql z^xum*;s|qG-`+dfYUpv=E>u9VD&E74Dm}s}C+~i$7mFNjeaEuW~cC|13pN@^AQf z)9b55FY?`?zJWqKNp81P!aQyH9Yy^%EXU@j$H=`ant9ZpL$@CVYy9%LMM>l76Hd*J z4hsfW@BL0=(c1%J32aS>?-n*{^e&Q(fSSkQq$gn^!r2#tJF zI~jl#rep{v>?r~sqb3VA&Rf68SD(%WL?IwR0*8nW59!vrNGDN(7%>%>lw9Ionv^AR z!0jDP@TH-lS#ACV2l+<{-5^;{6?OnrpZWeT)9;ZgdjlY0rSQ8&Hpqec)_$d0Qr<=G zN8(hYdou{wq8zd8_tM#pL<6}ZXLI%>6WaQ*x_4#ks_Ql_r1;1SN ze@TVTL*?Z&1S6^Hk+$Oha+RKX#An+ao#$uo*k`b=03iYpwVv|EP8AQKE(@Ty(Jo)B zT+pd6CY&e1exNkx0iRx50l+>{OG^t&;s8m7`4HK5#YzlvB+~QeY&veclLbz3et@s| zx7ffB5^N2k2FJu^>`BFxz8FyZpyg27v}S=>drX4gxUniR}^5KHT3&D^RyCT>u!_hOLk?72m*n~w|q=I z&^Lnt2u??Oh~|Y-J`p13Flt&e$n804h!wgRblAWy0l1=`?Nhweiml$^~Z)_kynw2($lZATLY`&oK^qePUSA&Yt3~(h0kpn0t>*l9)N1Iy|m#gV8ACOUaGLKuoF0 zt@q7i(2fiu>SDG_;w0uxRv}iSbE`HK{hwml|Etf|x!}241OerZC)rr~4NXLR;{E#8 z={EwxmNhN9yeBw%OQX8KLm~XAY_hfaQz=hEv=^;j(2k;Uu@1X{rs+8j z{$ncUaEprg%Aqi2=UR!^He;-kcFj)MUJ;iLx08M2h7&`qdY_D{r-3qZfb1yN`U(3O z$6nXug`VV?v&1!1L_uk%wnPM*&PLg|*<`Cb>N5P+)gUd0{dXN&qodW&WJ(OgFPkXH zMU{m{59d4Mtfz)+#Uw$wuWsMH$}VQfV1|WqJr0l6=U)+$ zxxy`iwy4&WGZ-ta=a{o}+LmOW!!+-EGe^=cba3a`QPnB2X6ww5*{^@@N!`gZB~`R2 z_q=lw#3v_{cC0Oo_kNuJ>~6M}%`lV0yzjgrFZqo=|F`*cRNt)IzWmU{MwvRg*o>^b zv2}P&t#IeTP}gt3g>!M(4VB!UG8TBJEL%SmR{K-yzNPO2Bcv2uz|jSDI-=N$h_ zjzo@uD=@L>Zf~MNrxGt>P$%RR=Dng)C-n0@^0$O^#LW2m@tNd}`Zz8HBiWD{KCdyn zFgm(tW^T5Dii*FacOPf6VT_8lernch3~8r1-Q`(R@F9Axb?Pw-@wvh!*u{|`?d0OR zGuBh`jjOz5t5dQ{4=|!=)(I6={x+(`ozHvM5Uc6K2RHZ7&B>@DW`LWfdzw?ew?!$r zUS>ON?~|fcm!M#MUySFz`vLpA(^pL0KDa|y`#}80CbP1=u-j*u61Ixt7qKtjXoNZP z7bV4RmBGlD+@6rig-MssKF04@F%A`_qrVd~pstT)e`SilB9>LmXN3?cXT_RrJC7IV zj9^}SP$xuQvdUPd)T^*iT%( zJ-^(kvC~8mSXMr%^{~b8K2}vZTfj769}a%g^<)3}u!U@)F1n(H?f0COk4>AtM`}Hk zfK@!c`BEQiTcTUSS}BpK-=6AC8ku8pv=<3akEUbk+n_zxTN@YdmLh^tSfM8je8 zcK+ArYt0EAW_h{nHm3csV4p#4&-e=!>)k$?qWbglxU{SnDFtksI}eb*TEm3;ZP##Q zoU)LD!{s?{ibu>BxQEcoMK5B|!iqSuEpKdxT08o!4hcWDe@`rMy!FH;dyl)?J~==) ziJz64fFzv$)}r28jO*x}-CnW&PNi`MU7xRib^m$I`9a=(L2HeU1SZSI@=@UAj|yR2 zKa-u|+Q<-TLB(I2Vw7<4>9r9lKaIvO)ujx(R8H9LOKvnBZ@64Kernwk=nr`_LH744 z!B_oMd*sA66}p04x{M36fUv>Ymf+0G>NJ?q4zs-XkPNxvm(aYG;}AC(=!g)&3eYty z+nc-@U4BH*F&y}2rs=ebH~4$2O@&45be7>RO?`B+)3mgzA$$$@i~oBTsXj|0QZoC! zFb-}MB@JfDq<0z{Rdi^#lV8)Ul5e%QeFn3ua0-5z)5S0Y1A>l_>{{Ph`)~={X75As zIAZ60S#H&=l}}ISaf-ZB>k)5t3_W*&B(^O22|LU%z6Df5(80Uyu2O~cb0>QVceBA?#ki>8iN{y*{&|A-ZX{2y9`kZk{SCWnmG zl<{>>-0I594lUfaO%G)8U-R-PI84%3t8m+?SqK4sQz?s}AV8&9|alNf%+Kv zgz|H)x}YnG+KrIL*l3m->BM8bk8soRG^Fu@6d5uR18;K zwUMW5*Vz1D%=@e@cRxeY^TcTyL^e0ZRIb3RJ);9UaMqfl4T>>47Yr8GF>+zBc7x}e z&PY<7mFvCvnioTYm%0&sbquF&Ra`~+?BjtKt~q?zv^-VWstlP^yFe!pSI#ef^lZ4k z{J?;NjDwG_VbKWAY0j9MRzn{9V{U#`_CsO5Z_)F8J+-wS^`@uys_5#5udc4j^yHNH z621OOr~bb#Ef8R+U9uMS(wK11&1Vx!S=Oy=Q|}~f$o^zVaEI%IV9I=0y3=64BxGW0 z8khKxA@X^7e}8}UF6R4pAS9_$pBMglx*4ltgRzm(Yuj1QCqzcTY4J_k9UxeJ00Hs= zp#6-9QTXk`Zl;v_NdinsA*ny8UY zi!(1dIn>{Z>5*GJ1Ef~nNx>l0=ORJFo6_Kkr$m)YRYamRdOBs!LHw0_DsBS7BtK59W6tpzl$ z_i+dQw;q!x01yxmpsRlf))s%QD=MU^sYz=Z^tsq07$r^E~x}+;4n9zXWu`lOYti#Oxcde@icr6ufi{aMlTiE3eSOHZ(Lmy1eWH z-j66?MhvU6xVyh!IXtxIAk`V7wORODq9(NVd~ifZ{ldn)n%bCAxUICnGnUq`?Ng__ z&*x`o!$9N_mylQin`1GY0kiH@BYR5v`U3=_$b`)s^z8qpOI|iU-0ZS12^juuBHg|O zdk*wGR1zM{qQ;xto|~`#?6cp8{`+U~Gz2+-{RCRy`Rk^Ouc;8th>lPBQ9ugh50A^r$6a~VTs#42aPQQM6*DK-EPr zs9X=L1Y&p?x!)ZYpfB5j9vuDc+pqz;=az z|EC&gz<}O(+(~Tz!`8YUczRme+S)eEFO0h)gA{VwfP3+{pJPa~{wLE=GBe4xz4^`3 z3?q+5Q%`%EC)f=PAeL4T=_}vP050JONWw2!SkQs#xa02nbicMtIn8x{sY$p{x5j9S z6h*%UtS6R+Lt$@D>Ck$rU|AZQaqxmi^-cexLtcO4#Yz`EL)GHOz-49#S?iNpxR{>n zByfxz`9im16u1)iW-IzO3nb0A&ppo$mzp{^^y04TjFUCq5n73Q)#;G_wK}53eK5PK zNr_57TTftqp!EG+Nz<<=WO3uzxZ ztKN5-n;tr+EO*m;)Xdnx|L0P-rqqVRXnhHvrZy&*BaSwY&3E&Nxu{*Vv^-AF*IGoy zNzzr>u2^KKs8-=6#l={ei)1Qg0Ac=1M1%y$qs*Oi)s8RUMUsR9dmaP> z1JgY)5F|$gRwFbt6!MRa#ff>8mX?N| zh*;y*_Ryn~lP3;4Iw`3)l8UO-e`p!3y`S*s7ZM{@DS&zV5%?dn!@z6*P5s5JHO(;~ z&?11sV6@U2q(1iAcj1rnOUr9;XrAslQf{dN`GeC3&eU+7oBe!^a|r1>@pi`QUVK2| z18y8J5>FX!L*^wVB@AGR#0#`5mUnl<0HtLFjx%6lKESQAihZgz_la@b6|F;NNG z10$rtr~HrTn(w)Tt%L#5_49VvE6oN@!QsD8Np8pt;eS27%=`lV=aT;l*Z%}%Za)#% zCqiGf1l$0M>AUY6w+#p8gDEQtA6~tB_3K@QG?+oe!ed?@Jw!E)S|9N8DRx!SL5)R1 zMs9toTgk~`!Vgz)r2MY!8U{WaF0-9Y2YP9YWxYJ7eh=4M(aFiyr9!l{h=3Xvm6H0R zw|%xZGxnEV)rBmwdvLI`-s2P#A3p?;h3kOe0>oV_|6#rHq=K5BI=GXG3RoOR-~tUN z7ba_LY_ymvBppl>4Ew8+Bjd=*IJH!yUo*cFYNn=8H!1lVY1mRiz51W`9?kD|?x zcf1Su)B2m8JS0GG0T%09OpGzMJ&1n-0r%J7^oN5QBy9)`-l8Bho_rPIgdESB9v}D- zSr;^}PzzzfG02jRq2VgZ;QP1}xa9Xp3Z#K|c6Kblh(vpD#SNj7@~I|aq7A`GD3@Q^ zJb5k>&|^)rt&czlWCSd+?x1fRsj${?_wcC6e*gzw;_>1Bc+u<7@Zs*-{jlNkDT=}R zj=ow1hor>o(vA)X*~HAusQ(Asm&nM@L=N-*G>?z}hGD?5K!7YNv;{7vjluMbV+VmH zL#aq#a2tQP??1}}juyf@RBclco$AUDG&Vrm39kHmKb1K#{)4Ks9mtROs(G%Z40uQgm~cg z+G2ONRA5MmY#(2$f+zD=s&efD={wK!ote~h$NAFHH`7)2Y*1E7J)SB{tAem+^r2C*^~t^D}5tk~Ks?Ks}{9Aji#we%3ESgt|AJ>Z+Vy zVVH*#bE5-8@EaXJkkP@DL6g*+oSbntK?cYZek3T2NILH!#5jJq06J@b@X8{V@iK8D!rU@Z52w6`^jF zjKd5S81@Q+=aLVAVhN%e*1*6(E?tNeh)-@F{CAg4j~xK_h6D0i6LqQ5mUwe8H4Kzx zBajQLJ_lu* zfEds*z|E~oQ<*^sw}EyT6Av#KC~`)N^&TYkE(TcB@YGKp=tyr@f~-|0b+4=-C{kg29tljZXN^q3b3 zIGZOskpJ;LD1HtYmF%I51amlb~3N l^?zm!{=aus_xS_)v(BRA8ARS&@N0RHw1k3qq3DNz{|{qwA({XH literal 0 HcmV?d00001 diff --git a/js/mpc.js b/js/mpc.js new file mode 100644 index 0000000..bf2d969 --- /dev/null +++ b/js/mpc.js @@ -0,0 +1,187 @@ +// Written by Mike Frysinger . Released into the public domain. Suck it. + +function Mpc(socket, cb_update_state) { + this._socket = socket; + this._cb_update_state = cb_update_state; + this._queue = ['init']; + this.state = {}; +} + +Mpc.log = function(msg, obj) { + console.log('mpc: ' + msg, obj); +} + +Mpc.prototype.send = function(msg) { + this._queue.push(msg); + this._socket.send(msg, function(x) { + Mpc.log('send: ' + msg + ':', x); + }); +} + +Mpc.prototype.recv_msg = function(lines) { + curr = this._queue.shift(); + Mpc.log('recv: [' + curr + ']:', lines.join('\n')); + curr = curr.split(' '); + + switch (curr[0]) { + // Needs to return a list of dicts (see above for dicts). + //case 'playlistinfo': + case 'currentsong': + case 'stats': + case 'status': + state = {}; + lines.forEach(function(line) { + i = line.indexOf(':'); + if (i == -1) + return; // Ignores the OK line + key = line.substr(0, i); + val = line.substr(i + 2); + state[key] = val; + }); + this.state = state; + this._cb_update_state(state); + break; + default: + this._cb_update_state(lines, curr); + break; + } +} + +Mpc.prototype.recv = function(msg) { + /* We can get back a bunch of responses in a row, so parse them out */ + /* XXX: Do we have to handle partial reads ? like long playlists ... */ + lines = msg.split('\n'); + var i = 0; + while (i < lines.length) { + if (lines[i] == 'OK' || lines[i].substr(0, 3) == 'OK ') { + this.recv_msg(lines.splice(0, i + 1)); + i = 0; + } else + ++i; + } +} + +/* + * Command generator helpers. + */ + +Mpc.__make_send_void = function(cmd) { + return function() { this.send(cmd); } +} + +Mpc.__make_send_arg1 = function(cmd) { + return function(a1) { + if (a1 === undefined) + Mpc.log(cmd + ': function requires one argument'); + else + this.send(cmd + ' ' + a1); + } +} + +Mpc.__make_send_arg2 = function(cmd) { + return function(a1, a2) { + if (a1 === undefined || a2 === undefined) + Mpc.log(cmd + ': function requires two arguments'); + else + this.send(cmd + ' ' + a1 + ' ' + a2); + } +} + +Mpc.__make_send_opt = function(cmd) { + return function(arg) { + if (arg === undefined) + arg = ''; + this.send(cmd + ' ' + arg); + }; +} + +Mpc.__make_send_range = function(cmd, min, max, def) { + return function(arg) { + if (arg === undefined) + arg = def; + if (arg >= min && arg <= max) + this.send(cmd + ' ' + arg); + else + Mpc.log(cmd + ': arg must be [' + min + ',' + max + '] but got "' + arg + '"'); + }; +} + +/* + * Querying MPD's status + * http://www.musicpd.org/doc/protocol/ch03.html#idp118752 + */ + +// clearerror +Mpc.prototype.clearerror = Mpc.__make_send_void('clearerror'); +// currentsong +Mpc.prototype.currentsong = Mpc.__make_send_void('currentsong'); +// idle [SUBSYSTEMS...] +// TODO +// status +Mpc.prototype.status = Mpc.__make_send_void('status'); +// stats +Mpc.prototype.stats = Mpc.__make_send_void('stats'); + +/* + * Playback options + * http://www.musicpd.org/doc/protocol/ch03s02.html + */ + +// consume {STATE} +Mpc.prototype.consume = Mpc.__make_send_range('consume', 0, 1, 1); +// crossfade {SECONDS} +Mpc.prototype.consume = Mpc.__make_send_arg1('crossfade'); +// mixrampdb {deciBels} +Mpc.prototype.mixrampdb = Mpc.__make_send_arg1('mixrampdb'); +// mixrampdelay {SECONDS|nan} +// Note: Probably should handle javascript NaN here. +Mpc.prototype.mixrampdelay = Mpc.__make_send_arg1('mixrampdelay'); +// random {STATE} +Mpc.prototype.random = Mpc.__make_send_range('random', 0, 1, 1); +// repeat {STATE} +Mpc.prototype.repeat = Mpc.__make_send_range('repeat', 0, 1, 1); +// setvol {VOL} +Mpc.prototype.setvol = Mpc.__make_send_range('setvol', 0, 100); +// single {STATE} +Mpc.prototype.single = Mpc.__make_send_range('single', 0, 1, 1); +// replay_gain_mode {MODE} +Mpc.prototype.replay_gain_mode = Mpc.__make_send_arg1('replay_gain_mode'); +// replay_gain_status + +/* + * Controlling playback + * http://www.musicpd.org/doc/protocol/ch03s03.html + */ + +// next +Mpc.prototype.next = Mpc.__make_send_void('next'); +// pause {PAUSE} +Mpc.prototype.pause = Mpc.__make_send_range('pause', 0, 1, 1); +// play [SONGPOS] +Mpc.prototype.play = Mpc.__make_send_opt('play'); +// playid [SONGID] +Mpc.prototype.playid = Mpc.__make_send_opt('playid'); +// previous +Mpc.prototype.previous = Mpc.__make_send_void('previous'); +// seek {SONGPOS} {TIME} +Mpc.prototype.seek = Mpc.__make_send_arg2('seek'); +// seekid {SONGID} {TIME} +Mpc.prototype.seekid = Mpc.__make_send_arg2('seekid'); +// seekcur {TIME} +Mpc.prototype.seekcur = Mpc.__make_send_arg1('seek'); +// stop +Mpc.prototype.stop = Mpc.__make_send_void('stop'); + +/* + * Connection settings + * http://www.musicpd.org/doc/protocol/ch03s08.html + */ + +// close +Mpc.prototype.close = Mpc.__make_send_void('close'); +// kill +Mpc.prototype.kill = Mpc.__make_send_void('kill'); +// password {PASSWORD} +Mpc.prototype.password = Mpc.__make_send_arg1('password'); +// ping +Mpc.prototype.ping = Mpc.__make_send_void('ping'); diff --git a/js/tcp-client.js b/js/tcp-client.js new file mode 100644 index 0000000..8d1db93 --- /dev/null +++ b/js/tcp-client.js @@ -0,0 +1,229 @@ +/* +Copyright 2012 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Author: Boris Smus (smus@chromium.org) +*/ + +(function(exports) { + + // Define some local variables here. + var socket = chrome.socket; + + /** + * Creates an instance of the client + * + * @param {String} host The remote host to connect to + * @param {Number} port The port to connect to at the remote host + */ + function TcpClient(host, port) { + this.host = host; + this.port = port; + + // Callback functions. + this.callbacks = { + connect: null, // Called when socket is connected. + disconnect: null, // Called when socket is disconnected. + recv: null, // Called when client receives data from server. + sent: null // Called when client sends data to server. + }; + + // Socket. + this.socketId = null; + this.isConnected = false; + + log('initialized tcp client'); + } + + /** + * Connects to the TCP socket, and creates an open socket. + * + * @see http://developer.chrome.com/trunk/apps/socket.html#method-create + * @param {Function} callback The function to call on connection + */ + TcpClient.prototype.connect = function(callback) { + socket.create('tcp', {}, this._onCreate.bind(this)); + + // Register connect callback. + this.callbacks.connect = callback; + }; + + /** + * Sends a message down the wire to the remote side + * + * @see http://developer.chrome.com/trunk/apps/socket.html#method-write + * @param {String} msg The message to send + * @param {Function} callback The function to call when the message has sent + */ + TcpClient.prototype.sendMessage = function(msg, callback) { + this._stringToArrayBuffer(msg + '\n', function(arrayBuffer) { + socket.write(this.socketId, arrayBuffer, this._onWriteComplete.bind(this)); + }.bind(this)); + + // Register sent callback. + this.callbacks.sent = callback; + }; + + /** + * Sets the callback for when a message is received + * + * @param {Function} callback The function to call when a message has arrived + */ + TcpClient.prototype.addResponseListener = function(callback) { + // Register received callback. + this.callbacks.recv = callback; + }; + + /** + * Disconnects from the remote side + * + * @see http://developer.chrome.com/trunk/apps/socket.html#method-disconnect + */ + TcpClient.prototype.disconnect = function() { + socket.disconnect(this.socketId); + this.isConnected = false; + }; + + /** + * The callback function used for when we attempt to have Chrome + * create a socket. If the socket is successfully created + * we go ahead and connect to the remote side. + * + * @private + * @see http://developer.chrome.com/trunk/apps/socket.html#method-connect + * @param {Object} createInfo The socket details + */ + TcpClient.prototype._onCreate = function(createInfo) { + this.socketId = createInfo.socketId; + if (this.socketId > 0) { + socket.connect(this.socketId, this.host, this.port, this._onConnectComplete.bind(this)); + this.isConnected = true; + } else { + error('Unable to create socket'); + } + }; + + /** + * The callback function used for when we attempt to have Chrome + * connect to the remote side. If a successful connection is + * made then polling starts to check for data to read + * + * @private + * @param {Number} resultCode Indicates whether the connection was successful + */ + TcpClient.prototype._onConnectComplete = function(resultCode) { + // Start polling for reads. + setInterval(this._periodicallyRead.bind(this), 500); + + if (this.callbacks.connect) { + log('connect complete'); + this.callbacks.connect(); + } + log('onConnectComplete'); + }; + + /** + * Checks for new data to read from the socket + * + * @see http://developer.chrome.com/trunk/apps/socket.html#method-read + */ + TcpClient.prototype._periodicallyRead = function() { + socket.read(this.socketId, null, this._onDataRead.bind(this)); + }; + + /** + * Callback function for when data has been read from the socket. + * Converts the array buffer that is read in to a string + * and sends it on for further processing by passing it to + * the previously assigned callback function. + * + * @private + * @see TcpClient.prototype.addResponseListener + * @param {Object} readInfo The incoming message + */ + TcpClient.prototype._onDataRead = function(readInfo) { + // Call received callback if there's data in the response. + if (readInfo.resultCode > 0 && this.callbacks.recv) { + log('onDataRead'); + // Convert ArrayBuffer to string. + this._arrayBufferToString(readInfo.data, function(str) { + this.callbacks.recv(str); + }.bind(this)); + } + }; + + /** + * Callback for when data has been successfully + * written to the socket. + * + * @private + * @param {Object} writeInfo The outgoing message + */ + TcpClient.prototype._onWriteComplete = function(writeInfo) { + log('onWriteComplete'); + // Call sent callback. + if (this.callbacks.sent) { + this.callbacks.sent(writeInfo); + } + }; + + /** + * Converts an array buffer to a string + * + * @private + * @param {ArrayBuffer} buf The buffer to convert + * @param {Function} callback The function to call when conversion is complete + */ + TcpClient.prototype._arrayBufferToString = function(buf, callback) { + var bb = new Blob([new Uint8Array(buf)]); + var f = new FileReader(); + f.onload = function(e) { + callback(e.target.result); + }; + f.readAsText(bb); + }; + + /** + * Converts a string to an array buffer + * + * @private + * @param {String} str The string to convert + * @param {Function} callback The function to call when conversion is complete + */ + TcpClient.prototype._stringToArrayBuffer = function(str, callback) { + var bb = new Blob([str]); + var f = new FileReader(); + f.onload = function(e) { + callback(e.target.result); + }; + f.readAsArrayBuffer(bb); + }; + + /** + * Wrapper function for logging + */ + function log(msg) { + //console.log('tcp-client: ', msg); + } + + /** + * Wrapper function for error logging + */ + function error(msg) { + console.error('tcp-client: ', msg); + } + + exports.TcpClient = TcpClient; + +})(window); diff --git a/launcher.js b/launcher.js new file mode 100644 index 0000000..a4b91cc --- /dev/null +++ b/launcher.js @@ -0,0 +1,10 @@ +// Written by Mike Frysinger . Released into the public domain. Suck it. + +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('main.html', { + bounds: { + width: 300, + height: 120 + } + }); +}); diff --git a/main.html b/main.html new file mode 100644 index 0000000..8f5e3c4 --- /dev/null +++ b/main.html @@ -0,0 +1,125 @@ + + + + + +Media Player Client + + + + + + + + +
+ +
+ + + + + + + + + + + + +
+ + + +
+ + + +
+ Loading... +
+
+ + + + + +
+ + + + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..08efb72 --- /dev/null +++ b/main.js @@ -0,0 +1,236 @@ +// Written by Mike Frysinger . Released into the public domain. Suck it. + +/* Globals to allow easy manipulation via javascript console */ +var mpc; +var tcpclient; + +function TcpClientSender(tcpclient) { + this.tcpclient = tcpclient; +} +TcpClientSender.prototype.send = function(data, cb) { + this.tcpclient.sendMessage(data, cb); +} + +function tramp_mpc_recv(data) { + mpc.recv(data); +} + +function sync_storage(sync) { + return sync ? chrome.storage.sync : chrome.storage.local; +} + +window.onload = function() { + var local_keys = [ + 'sync', + ]; + var sync_keys = [ + 'host', 'port', + ]; + var options = { + 'host': '192.168.0.2', + 'port': 6600, + 'sync': true, + }; + + chrome.storage.local.get(local_keys, function(settings) { + local_keys.forEach(function(key) { + if (key in settings) + options[key] = settings[key] + }); + + var storage = sync_storage(options['sync']); + storage.get(sync_keys, function(settings) { + sync_keys.forEach(function(key) { + if (key in settings) + options[key] = settings[key]; + }); + + init_ui(local_keys, sync_keys, options); + mpc_connect(); + }); + }); +}; + +function mpc_refresh() { + mpc.status(); + mpc.currentsong(); +} + +function mpc_connect(host, port) { + if (typeof(host) != 'string') { + host = window['opts_host'].value; + port = parseInt(window['opts_port'].value); + } + + if (mpc != undefined) { + console.log('disconnecting'); + update_ui('disconnect'); + delete mpc; + tcpclient.disconnect(); + delete tcpclient; + } + + update_ui('init'); + tcpclient = new TcpClient(host, port); + tcpclient.connect(function() { + var mpc_sender = new TcpClientSender(tcpclient); + tcpclient.addResponseListener(tramp_mpc_recv); + mpc = new Mpc(mpc_sender, update_ui); + console.log('connected to ' + host + ':' + port); + mpc_refresh(); + }); +} + +function tramp_mpc_consume() { + var val = zo(!getToggleButton(this)); + mpc.consume(val); + setToggleButton(this, val); +} +function tramp_mpc_next() { mpc.next(); } +function tramp_mpc_pause() { mpc.pause(); } +function tramp_mpc_play() { mpc.play(); } +function tramp_mpc_previous() { mpc.previous(); } +function tramp_mpc_random() { + var val = zo(!getToggleButton(this)); + mpc.random(val); + setToggleButton(this, val); +} +function tramp_mpc_repeat() { + var val = zo(!getToggleButton(this)); + mpc.repeat(val); + setToggleButton(this, val); +} +function tramp_mpc_seekcur() { mpc.seekcur(this.value); } +function tramp_mpc_setvol() { mpc.setvol(this.value); } +function tramp_mpc_single() { + var val = zo(!getToggleButton(this)); + mpc.single(val); + setToggleButton(this, val); +} +function tramp_mpc_stop() { mpc.stop(); } + +function zo(val) { + return val ? 1 : 0; +} +function szo(val) { + return val == '0' ? 0 : 1; +} +function getToggleButton(btn) { + return btn.style.borderStyle == 'inset'; +} +function setToggleButton(btn, val) { + if (val === undefined) + val = !getToggleButton(btn); + btn.style.borderStyle = val ? 'inset' : ''; +} + +function show_page(page) { + if (typeof(page) != 'string') + page = this.id.split('.')[1]; + + var eles = document.getElementsByClassName('main'); + for (var i = 0; i < eles.length; ++i) { + var ele = eles[i]; + var dis = 'none'; + var cls = ''; + if (ele.id == 'main.' + page) { + dis = ''; + cls = 'selected'; + } + ele.style.display = dis; + document.getElementById('tab.' + ele.id.split('.')[1]).className = cls; + } +} + +function update_local_settings() { + var setting = {}; + setting[this.id] = this.checked; + chrome.storage.local.set(setting); +} + +function update_sync_settings() { + var setting = {}; + setting[this.id] = this.value; + var storage = sync_storage(window['opts_sync'].checked); + storage.set(setting); +} + +function init_ui(local_keys, sync_keys, options) { + /* Setup footer */ + [ + 'controls', 'metadata', 'options', + ].forEach(function(id) { + document.getElementById('tab.' + id).onclick = show_page; + }); + + /* Setup control tab */ + ui_mpc_status = document.getElementById('status'); + ui_mpc_metadata = document.getElementById('metadata'); + [ + 'consume', 'next', 'pause', 'play', 'previous', 'random', 'repeat', + 'seekcur', 'setvol', 'single', 'stop', + ].forEach(function(id) { + var ele = window['ui_mpc_' + id] = document.getElementById(id); + ele.onclick = window['tramp_mpc_' + id]; + ele.title = id; + }); + + /* Setup options tab */ + document.getElementById('connect').onclick = mpc_connect; + local_keys.forEach(function(id) { + var ele = window['opts_' + id] = document.getElementById(id); + ele.checked = options[id]; + ele.onchange = update_local_settings; + }); + sync_keys.forEach(function(id) { + var ele = window['opts_' + id] = document.getElementById(id); + ele.value = options[id]; + ele.oninput = update_sync_settings; + }); +} + +function update_ui(state, cmd) { + if (typeof(state) == 'string') { + ui_mpc_status.innerText = ({ + 'disconnect': 'Disconnecting...', + 'init': 'Connecting...', + })[state]; + return; + } + + if (Array.isArray(state)) { + /* + switch (cmd[0]) { + case 'setvol': + case 'seekcur': + break; + default: + mpc_refresh(); + } + */ + return; + } + + if ('file' in state) { + // Hack: should be a real object. + ui_mpc_metadata.innerText = state['file']; + return; + } + + var time = state.time.split(':'); + window['ui_mpc_seekcur'].max = time[1]; + window['ui_mpc_seekcur'].value = time[0]; + + window['ui_mpc_setvol'].value = state.volume; + [ + 'consume', 'random', 'repeat', 'single', + ].forEach(function(id) { + setToggleButton(window['ui_mpc_' + id], szo(state[id])); + }); + + ui_mpc_status.innerText = ({ + 'play': 'Playing', + 'pause': 'Paused', + 'stop': 'Stopped', + })[state.state]; +} diff --git a/makedist.sh b/makedist.sh new file mode 100755 index 0000000..76be818 --- /dev/null +++ b/makedist.sh @@ -0,0 +1,42 @@ +#!/bin/bash -e +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +case $1 in +-h|--help) + echo "Usage: $0 [rev]" + exit 0 + ;; +esac + +json_value() { + local key=$1 + sed -n -r \ + -e '/^[[:space:]]*"'"${key}"'"/s|.*:[[:space:]]*"([^"]*)",?$|\1|p' \ + manifest.json +} + +PN=$(json_value name | sed 's:[[:space:]]:_:g' | tr '[:upper:]' '[:lower:]') +PV=$(json_value version) +rev=${1:-0} +PVR="${PV}.${rev}" +P="${PN}-${PVR}" + +rm -rf "${P}" +mkdir "${P}" + +while read line ; do + [[ ${line} == */* ]] && mkdir -p "${P}/${line%/*}" + ln "${line}" "${P}/${line}" +done < <(sed 's:#.*::' manifest.files) +cp manifest.json "${P}/" + +sed -i \ + -e '/"version"/s:"[^"]*",:"'${PVR}'",:' \ + "${P}/manifest.json" + +zip="${P}.zip" +zip -r "${zip}" "${P}" +rm -rf "${P}" +du -b "${zip}" diff --git a/manifest.files b/manifest.files new file mode 100644 index 0000000..e391a0b --- /dev/null +++ b/manifest.files @@ -0,0 +1,6 @@ +images/icon-128x128.png +js/mpc.js +js/tcp-client.js +launcher.js +main.js +main.html diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..14453b1 --- /dev/null +++ b/manifest.json @@ -0,0 +1,20 @@ +{ + "manifest_version": 2, + "minimum_chrome_version": "24", + "name": "Music Player Client", + "version": "1.0.1", + "description": "Control a Music Player Daemon (MPD)", + "icons": { + "128": "images/icon-128x128.png" + }, + "app": { + "background": { + "scripts": ["launcher.js"] + } + }, + "offline_enabled": true, + "permissions": [ + "storage", + {"socket": ["tcp-connect"]} + ] +} -- 2.39.5