From b10f3abd0ee3f446ec3ea12d1545018a047ac743 Mon Sep 17 00:00:00 2001 From: Peter Steenbergen
F#)FZV{leg=Sk;9J& zYA}b|2D)js2HH!_@=q5FtK*R1oCH5Xn4oCK7-$z!9`+!LYBZgn7>8cW-fur z>fkQ20Xy~XXDB2{Ndu~`g`yc4RNZ-JR;us0WG3ac(GZI8$zeTAyjn=+N=i5TbcOjT z(#EeqjVKeIw*4JleM9?B5V$Ol3yqha$og51XMISO=!A>$X*=R9@2($z#L7NL9>XQz z`%r|_e4qQ|DJ~1-V=JG9@UKd{xhP-9M@=IHxVzXy^tZ4UwzjSOmNwemOA1zdvamS~ z#t87(CedP82*H3I#l7&E-!C6IpS5rQ`7-GnKuu;t`D|}(jUVqp9?DrgZI3JjveAB} zh}y!5U>e)SMN^ox?vf@71k&+p-h?QlKRK`BH_>H;`E?=eV2Vro>#b4JsqSHOqxP+o z?mT!g?d8W6NP_t0*W;j=gu}vj1!eXh6DWu-ruO&JKM8TL$`upGKvOWRi7wy>Zug82 zNiN>vO{4d4k5kT@Unw8Faellm1{Zm^*Gf69m`o=SHpUxvl(Jv _>31j!X^RBLY^q-==atbnUFuU$$h{ss;yn^oiSlPfWk=g&w_*NOq z5aNp|)TP(I+I|U;)zL|SSCR^VmEuojB#8EX7;5%{*=|T1 Q>e@cxgJqf#UdN|6qf8@s?CtlBRqRI z$E%t}B!++s7mkPdK|E43O-I=<9lUFog7uvJU?!c7E3@Y@*5R(ZuuL;W*ItEcuzUd7 zN9dk*5eDf7vjv^o)C5uhB4uoomF%_lfC{C)`tiH^7NRbFEcUgnygEz*b#oq+PgBGs z;|-fPEQy!b{$S$doqG5%!Ooqs{0|GeE48{TN!ehIh9CljA;W Nr7RW6|uNa(eR7yLn$zLgx;B6EXC74ip*>9$alAP$9ZTk Y@51Ec5CDK4$edk*)Zt@;PBTq>HxqjhiXAOgFk>1%;=EqZLB zq 2m;KP6Zal`RpekY-Qylum*)iqv^HfR1eEwpl+oIb}Y{e(gP-u0>#^U^Cf z6+?kof0v^u=?(4}Eu)eTG*BbId8i1?h2E@3+veNb?QkBx<8S=3jJlFKECl;ivs@%s zQp=K4#)hZC+v5lXTComZYaZ0jG}e}20}5ym%kCF~{f+IidZb{eC`h{^Py;*-(i!H- zAN-JM8YjDGiTFA6noSrw`4#a3!KOzn;U8EBLJIs!BL@LtI(Hoi_y8znV%;GK+0qM@ zex1HfqizO9VrJp9IM_Xr+?1rHFWNX0X8V7ykXgG@%7)M!mMN) *T9^rZeSH1TJ f9@2p?9pXi@*} ziJ)9UErMCOvM-3HE-jGdHQP)QnJKQzSFe#{;6KM6gNx>=Q-5&V4hLx?iNb8y+Vl2u zKXTg}67j==5ev>w#hA|fKFYk$$&>$hjk83|4o$&=6IpOFNf1eF>XefosRisf68&-d zd{crRzOvX4iZIAed^7hTrGn+SIymVZ^=~Wjr!}}S-j2kmiG_R6>U0sL+4?ye *e(M+$v3Eu#NwTS}~FS)2}QFbu6fY zX>srAfGcuN l6bDCTbMZi^fd%*_>x=woxF(hMUK;jTq2|>mekIH zj-;%g$olCUtv~IbJaYS}glO3LKbpTOx4PrbkJn?R)Vk#?S#sV-#=ki|fls|N-1hCY zo;N7%B#5<*s-9K}j@Ww7zOZ?$(AQ9@y)O59PI|3Xut#0%Z@)akH~_UFLV%x&zT|$6 z^1F1I@c|#u?Bw zpL*1mtU}P$LT5gn3T@w7(N*mmsq81Rd|P$zuABFQGDJX9`edry<_)6!RiQo4QheR5 z%nU{=)8Oh847*YtlF~%2IRDD=(A6oS>s-=TcsA>U_NmyZwZz9i?M^5?TQUpt4=#vm z*IkSrK7 EMGR*2FWsndl*d`ntLwrF_lf20CfO%+rlhDO40rWZ})@ z(7r$<{#n`UpDcdTlwyP(2f`1wk9gL(zwT26U%rD5(H7N!+GTR>G>EndFTqJ{Aza7@ zZEQX|gO;g{A?a@2cQrEJ?V6q~DsSD?)zRVyPR^E&^05E-R%S|Q!*0Gmf6}0O-)1`a z^DC(XD=`O(9Wp#YJnnnlRo!AebMLU=f>#cXSuA?`e`ZA~4N}Vb$9IJ^D`WpsAp2PC z!ELctf{@gEAvO;4xc23tn6wnW?VGl$3C*4=8r@p~3OEb%N%1Jn_p>#%6wCGl_#Zx$ zJciqVOe}Bq^Toe`7oM#AW*3`njeeH7PTW4n=-JF_p`VJ0wObY36FHQcJ@=#SW9OK) ziWjQ0G#qUmx!Dk{=~$G@mdqIPn-$Wh9TZA!p<1743WaTJX5q*O*fPqc#RTbBj;bSb z3+0_@yLn+!S~7%Sq~Bi`({gE&Ca&P@MkH8YEgckVwl3CR?w}i+;Abi5en3p!8u8#O zqM3M?JoFnHdii2=l7S@S6$`UvxD|0FoW%fkB1JvaUV~InSU(ON#485dLvY+U5aDDO z7Y#n?5`BYs$8$M;=VM_7-l$s1^4;g}a(8Hgf-Eheb8K`SwI#XE(nY3VkH6BcI_s>U zbzfOF5c#Z9qbKLP+3q+mhPmV5#+B1zVL#heR?xsp;U@$#R)V24lH;Kz6fvf!zTX7! z1S~ilR6k3ytd5eRe9iVXGCwl3NexgiKF7^etEUv>ZZjSIGq5vyzROdP?x?_y2BgGY zmzyO1Fekq-%efcbr)#YK>WUedfYUf%1nYlcpfAZphQ+Z+@}P0BP9LxEW`=BRzifTZ z k8ACVY{zTNQ$E`4MrA>x2MIqjd9P z&z894^PW6rdq~39e3^PP;(}To)z8vvH+Kf^r!1r_gxwPi%_!*MAFL_Nlqyt%FuHN4 zphf=3MP!88tV;TW_h(%qpzTucppPPyVp(kp76fcl)Eb?6n6;$XRoja=HSwz15eXP| zeuO68TStq2*BP?9Zz8{9-b6vWgSC5n3MeD$7nPOr&tpClDykJaej{EIFpX($_PjRU zO)5^YbNBvNOlbVMt(Q|^<@NT &Fq#Rh}z))zCSUC=nvoMKE&gCLwSW z0a D_v*i){TWjpFiM@z20 zP4 0Jy$L?fCUC)Z0$zf%>r=Ja&lidshVNkVrLxb)N zQNW7-woOCFU<71q49xfjuu}e6ncn>%NTH xdx4_K3hE=$;uWzsi!De!_-Pba zl+1r6vZj>NQBr;gqxM^`UW5qaGdc#vK_%*_*!d!qj8UOty5e$1!VZ=ODKgLzI)Pur zGVhthWJo>ypesCQma_P*1hLf-KhB|T9EU~x?xa=V#0#35>F2-PPKjH!h~2WJ+yv?t zNr$697TXvG9=91n+P@Etw9;OR;WJ)z>}Q)^K0LI?hsdRof>pp(%y|4xVHiv0z3JCK z?`ZQ<99fyJa7m=%JW+xwSy4Bwi$Jy<16i$)1tgNvSt*CB#G =ThFNu$SEh) z^kZNe*57)Cw30c Ezd62w=|JpP*C+RXQ4Lr( zwH6Y~MNBEaDrZ6P^pH)Av1eKsaXYZ@kU^%ve`gStDJ2?}K_>{q6vez_Q1%pfM*$mj z@e|4KKZ;2n`z%F|t}Bc;nm0?MJR5Ck*Xv&(3`AK;Q#pMA=hwfsqQ|rE`qCsbYvSpG z-Tudg?Gfl4iZbL|@m~G wtLhUkg&7W~O>1O2Oe znf;5`pu@l9A3@{cT2|UGT-^L^oncDaBI1$TJtvzDQU0t)kyk#gSD1VjGCCZcd}4~P zL(ffm+(qRy`@%LdhI}hmRasXALJJ$rvn1jt<(@Ytbg>+&VPQASmWM-3-qjoW*pmcl z2acHV-mklE4cEG{&%PQh1PBZ)OmnDL7`pnSN}Lcd-X;+m_5;D#U(;gLFB^@G^@TD| z8A;~w?5;m5dMriMLPyX77&5X85}hW(^GnlXSFb8L9(qu-Z`+~%YhRjOWBVb}S{{*& zq%gydS%(J!On#yuG1dH5%~mWFY2a1CcPT-V LYWU*C^VTT}XGiU0;u zmi_Rrfhim4>ng%y(U8f)cF3ZVTJ2n~uIlW;VtePy)rg^B&aF^3fs>(1P7!Cu`iUo` z7FqEj8m9A>US+bE=L|B!L< lHn$_^KhPAgXLNnL- zchb<(#>5ecitw}qpQ?@0L~qqJvwdY-r<)v#iohJg8H=}Z(h0Aw)7;tQzb-sMEr*Dw z1`1HryFKadijQO>xIE@OjGGPh$osc#5lt`HUNPWcUh8LITUKc}Y;kxle7do-ccWEt zBfl%vPmb45&J$Sv(9P6jgOjzianB-bZPe4CKBb4{R46Uz9(cn4^d`AL%?cA< (7nRMWu^(nffz+d ?K&gxOe9gqi@QjfYwWQ>73E6yb`Qx$ zGiqtc;I<&0AGI(8rmqW>q_yjQry=7F`^Gu};^_2f-#aBrB@ZSx#|ujbIoeAF$@ef{ z3qmOMzn)rIn)tFjhZ%Mho4z?z+?l^=wiPYeGzTTU3hvWc35FQDUAJT;46F0GA G)FZ&|XZ3Q5Tf?h~;;wA{W _eBf?cUpCzl&O4>3`in^eF+ZVlCba`^C5DRBZzP z6b2LDiSk$5k+tGYmF(NrYs~*f$0LJV$|&2T2l2bg`NpPIvi0w){_Mh|+0qB!$`AMK zG~`g1(~>*bWG;i(1KZVy>idDP=QkB5MIp~lV5Nfa>e|osrc29C^TL+8eR2WgG^V_l zr>#1(2B0Jky;WYjao=TbyEzmIZDKjAi61*D){Ji~HeF;-*0)Oz)9jtW)O9`1XV$%# zVhw?6`5Yr2Vx4Ap1|T#=F P?%Yk}KrNAPw*SQs6Xm*hqnjIN|V ztt0(0L%y6Er<8H-a96lxvnPA@QHtmaXP?&x*VKJ1aH^a3+wj$2d(;covXtx;y#5r? zBXbi7jOL*F=D8b$4)M^o$5-a>l7puY;oqg+zxV`tAAe=`{ew0BULPj*!wi}yKCbNV zcXy*po@joV?U?N<;iNG`$*d9Q^th4EubuM7Ves@Fcj~FFaT7DK3J=Rbhd;YpdkOnq z7PH#m_rJ_~r=o5P{z30|x`iD26#CeI`D~=ioV#-xkTdjxooJSh!*2u~cfn-yc7iLD z;y-syk~GaN-|SCLdR CChIMt4xHy;|cxs0`>3m`d@%6E8XYn{EhOB zr{AdhKEuI>bCNIWtsYfkYjyX>W2L8B`EXdRw17)AbKsredVWzG0ghI68mOAIf=o2S z@WV#*LMe`fAl)(jr>$@6FZ+0%Fi@W?-ipw*QT@3)q)^A-ucR3<*&pVV|FXCZyAT&* z#J*nCaFQZB92g3Epu!{mz|F~rwJCPjILCNBn$Li|1DWotW&6cmvuW;kbX7Qp{+;(J z0MB~UAdI8+ChQwnRXAVMkkOF~zjB3hyy(&3j#t|^`Ewp>^h9yiMcdrH?3-^+CPksO zcwWmcX)Q*vg@qIwdG{!VYNmtL*9v`FAZIRi4_jh2*XQq?>^={~{BZcT@b5+-WAAy{ z$lN5;^0nnerBfyH$|M|~qC7czI*5stRg5^|^>+Rj #~xaPXbLQ>OjKfd|CnLIHvuY?J>_y?3Y zzo4t*^OoIs*VBnhv_;cwOQg*|>xq zuZ&HTd}He94pQOFB+Aykpvx3 z-4m##dGe`!j Is~Q6B4WoDmw^->S%U+ zDa~Z^CgC_iL2YC+*>Na3<|e-B;Gs06Q%=XcBY <&yqEha_XRsE{-X&F4w$z(GRGv2cd;4&(P~7L7(=#wAgH Wj4-!pU9pRz4(Btp z;mQ)Wkp865yXu9vyCwLo{HO1kEI5HN49;9m>}Z+@n;$1?91?pUw+u4%hqfN=Hc^1h z1RiN{pK1KO3av>I)O8j8^(XT(s(y_y|K54>XL(o(X%I{yel_@y@v#r}%?8X*&hm*g z=5p|F2UgOD%jT@PU2oFszIW0F@0$pr^SAOlh(S2}57{MD{FTucCyf?$9^}$&uxVZ+ zdTc~eJ@7Xv5`v#iGH5;8!j#EMk{iIlbWf>DNcRH?1-%g%F{s$Q5wCQI1nVQnJ3w zlC&h=*?Vr~ED@`ZCO<+Gdi)xxXkX&L&U36UQQd`cYKQebgKqS`9_pS3l_#^E%VxMO zBgT>BFCGgbe { z0ljOExq6zVvz-<>wt24X0 xocOCz(_0Za(EHU)V+AgGCfY5H6anekmLq48U+9uE zy^Up@o4Hh7+6M1Ad-QZk0ULa WHIV52Hp*4rao{zWADYGU`z}%x`_)JyA825FAvRpg=K$> ;IK2Q|TWr$YY-7sQKbhGt&C37R*lXo9-PO>_kUT?v! z%4&5}cGbB!9_ce5@fMDKUH)C7X7dT*zngGLb2{_~B$eM~35qmB2J+Eh(C{5%OQo}+ zDMFO{rd#$tTTIc)Zhz;okTgY7BgDclI8Qp3O8H*l#JtK7+%GzQu?xAn7GK4y6V_hJ zZol%ttO5JOmRD1zHoe&@xRLAKl&m-gAME{7rz6=TW6m?NuB=7#JZfcN2v0Yf{A+zz z18N($^Vyx`Vo|9Wbi{DN*j&QwVrKe^UsA=^n RWBZZ-s*Hp9mWUZILR#vSY{LeG91~a^Zd9!0pIVfypMj}J% z=R)ENZHazeF0Bs4>ie>{ZJBj47HE(RE+`rMA9Ana($)T!<*`Vo*5WlEIwtMC8QweK zD}nv>(cT xw!BQ?R*x(@ttkhZJHkfw7YGZ_M^~cjBd|Vwpab)LjexQ1 zA@r8a 3uTjO4P |`DjtP!v-Q5k0;;S@0-0_FyjB!`!ox8RW`Za!bjXY zUT)k ;kD+{t5fRh_H67m^0N|O(DQq&4ALnUm{_Y(fAZ |L00U^V3o4{=dstVsB;8Hoo)X9)$E@+?oo88mHyP)Bh_k~ zeu&n;9NTLmPu{aH=jklk-dnN;bZ!LO=rOSW+0|dprs?8)>4Y*betj2Y))V`5pu^mq zw?Er-1Z6OC!)6)5rDTpA`I9i2ZEl#X@6Q)065W{1_G+`yST*UKN2If)sHdItl+~SX z^Fnfaqrs12s|r-?pO#n+t?0$KueV4e8cp^CVEaE+yL;9DL81cK{#ofCs5MQ0zsJOO zpqaCwsH1hw#strQ-0wGkpKd1t7bV@jc)D78|1gJze!|^nk-%%7VqFf07Ox~oCdF!{ zh4|lttNs34&vLLz0D0nMWXfpP+)%KuwB;KGnR?>LfQp=2*$CCuzSf9XqJEp^FOoA! zQ)RnGJ9vOpttyPN@LLGPrqN$Ur`2Lu(m_s_APaEYMQoc5mGaQ9a7&G)^q!^Pv?C(& z8MC-d{0iltHLnK=0S{N-F~&x08e(ybw`ezzUDqyDy#>e;tD~=Irm}NRogcjOzGUAQ z^LU95)onE0IcL7rS_b}!fX7-KMGTkIz({m#RU37a(29qytWGClx&1JgwFSa65&tN~ zLFF_1HOc|3bO $D$iQ&L~efCho$j@$cdyS1=sz@}zQGxat=``Vb z9L+cclaDsv#So*Gm3teS>18f7ST$Q9lVO+Ss)80aqAgxdGEwZUZN(DKXWBXYkJyd| zO0J5QR&a_fUA>`Q8Ea!dNLMA w0gII!QmjVI2NH~Tw9mzqtqu$G2&8<3Vk zmL$!eOnhs1kXvhH3r#(|#!vFQ6q0|^fHH0XWrq7B5FApkh4>3jp6b>w&+ZEsXx2wj zE@Bf77LC ac7C?jzG27fu}#6O;gG_k)u^5dBk|+q zKbaRUU^hK++duGyW^ZAExTQy`o16TuvJl#h!Ez3Ixyx)_h|a$d9bwZ>h(OcKcsBnY zfrDi`iu};UcuJm@i!6*|qMfd`h` 2fz0nsn9K9e8)v$_^z;`X zH#vKR{4r-4ak8WvdpvG{TwUR|2}^&l%ZV52%KCz5y3bAYc#dI~8^_DHPT=Y*hF;F^ zY>?EC#qzO)hxOffW=^R5NAJI8bqPZoz$Kt~>O&KO0XxSKNDx2MkNSg&kj%xl(CFN_ zMqoMQ5=d049hQ5F B!7Uz7jX4r7%7!l*Q- tmT z2oktKleLJiJfr-kk?c4*IPQ(J1pD}T3}?juw2h7W&;-Zuw?mR$`G;LeANx )V51EM~-jW@D@CsT@Nx23gyIV6^yoxV{oi2Oaw4UpzmZAbYaG- zh`PV#f;(C9*Q6|2R!blCNE)Ih2HF!0m6Z^f|D-DUEe|cG3u2$KVNTh=Hoxe*8tmA` z(Ea$Dys 4}Rk~k(=oaZ5!~V#0 z)IEn##yxt!cq1^B(8F{<$oiaF{fx-xUPSM(B61Q{LGZun%+gX%3kz=#4MmkDo6fSH z9krJ4C=)r7Hhy=@vZ^QW#6=2<4@~}97pehKg60M0lOcGt&@4Q<%xL#%;~v}`QOm?G z-Cdkxa1M;Uc11j=j73G>3f$7QHwjOTvb_8N-Yf~uMd;-`EWn=m+k`-Yh72MvhN)0* z&4maBL+M2|JWW5%?Gn}aQ_R~?!$n@>PBpVJNfLR%&`AT@iw(K?hY(rTUA@SU)p%Qz zm?te+|DFi5Hw~3*{yJNBg4xQ*XIz|?_rp3*`*;g`?tgj_ oeZPQ8uFlu*hOMX`z8NGY!#xFQhZum 6qYqOiiL;uRvW#(C zvx4`Z4ay{oweLC?Nz0t%iM;(3_9+w!XY#9J2-mJz47|%V5n;N5+Teh8;YjQf08feP z>7TU;SHQG6AK=qVkSAeYT@{sUBA0ed)|=D5LBp7|>G6k$Bf= D;6f}CQ}k5NBhZIA=SKB6`uIAgbElBu_3Bx_}jkR zwV7lP!(Bo+tG}xJ QHSi-CIV}F|I>OT1-o(&i%2Vw3;G7P zyJoFqYolW!k owBcb(*GblaP`OH`)5k zProlObHbm(%GmUE@)!8iZnlV2=?6~W&3BR~QsBYR!P#63`b#Q`YkySk@z2=NL5LW+ zX-P{kawt^f0ue{?6K`1vlYWMp>~)p{dnYmR*d!wIw@9I!1 &?PXV3w1V zLspNBJtvOn)+N2Jkod=4dpIXPG3Evx(h>x%!0p~F7VU^>MH{w4l=#-bx&`(`JU@UU zJ+@ihN=@ gJo?Xgzta{tmPE{`a+hWJ=2#nW3gi#hMC!f70Lw=ShX8 zu`%x3rFWk1i-bOsh4qpy>Cx=! (gp%lla z*YiMz&qLr1mxfvL9Ks8D+;--R_3IWBIcbzM4-dR!7xs+Hna8SxKWBaovM|YByQ~ zstvoPD?wLM%^PdugPmd- xVZN^n{+$mq`cpZlN1-kr z>g@@YU_}m!RSsK4_Rj<){c@K~6&IxI<9OsaDNp#}q8aGicqp&VeRSX%*Np2%c^K$E z@%VOqn#%P&n2K_$1!r9|h@1|owX*GCAUiK3B$ph$08(ZT_NAU;BIMp^JBuHI3)4s> zOW_Rg3?~!_?j44g^q?hcL^BzNLMdi ?dBXQ)O?_z2@FFIRGufAT?4`-^gR;?A z5j`kq8aL(tH0n&-RHj {X8kyb92sPw%U4Sm7zVTU`1YDA^+=YK7z>qhg@ z$`@34{{xP_rrRQP`N`Qf0kWg=BrlE I2a&W4x3$5n6E@XrJ%M(T(Br~2eGPi-WH97p{{5$V?7qUX;jmY7L z8c=%`i`je8Zl58#^$!PqhyqA`w8KyTH(d@sCyKs Yf5DCx!7ULPpg~7h57Ic{Ye+*!0cc1tKGOI`acz+tDzo^st;a@L&IMa3) 3S+k}Gu!)fy1H!l))y#D<|T|95# zlzucnG;IRs*g%|Ty9I2(j9cY5+>9p=uzO$09fJ96ivnaMNs{|Z0teb#&DE;&auH** zjQd4Hc27@FHW>VF+W*?|7whOu#^7%5jknmkb;zNZN+@-m9G;eW=$z!eac;@EsTTFA zv17boZ#8!ZE$xRd>##|fUFynkzkqCw;Y+-)!y~&4bb4qtQ3ILKYB5M|X}-QFnL+P0 ztSlJ#DEcoYU0l^}XS{KhMla8}s%fy4W{QtFU7MhXij85D91HK|Q;I~{N{(jj)+T(; zhL(Ce@#I+@7noypjo)Ifn#zpy7iSHa#3!kfCo&=4S#+(xTk7irj_Q3jiVb|<88`h1 z@O_o(ud;3Q+jETMUz0(jnWedRSD43vf3@lRy=fyRu?g6<4wL7Emb| 6> zgo-rN1 (t0pWEHf}*g__!uA!e<6vU-a@+tzQ+CzX_)ay(sk?E8-0jR!|A@22*A zd2v}le!yv=&%vmqz&hPun6E?YtowWFiT>Ra_l~?__}1p&x?wTD4wh-ZJu62PS-c$& zoV5z;39~Q~Ebf%-tncS~VOFshs2a?__!7C5CVb22C!`x5JCnDI^#hhe4yLB`>hZ{& z{R-?BV|=^ 8mH{<0l zh%n_-;CS-HIQ-@{Z0?;E96r85FDwJM7=O;hWeAxlZ$0g`g>^jYn`PqS9&Q&!HiTy( zFxopzB(9+QICvR4>*K3 @DezPwDrmR`AT@N}lr;f1*o&7$xSy~gxr*!zw5 zlp<9S16h*o39=v@GUpk6BWlcKCy)2Wf;04KskBx1z}ChZIo7{+AmPT7V!%EV)~XD4 z=BfnK om}dQ8WdvgsNcB$ z-NWkZ5kYCl@5~d+@7wh3Ym|X~GeVG8%3N(&UE^eIwN-;qVCPG0Y<3+=T1@P8ln_ zobA_7&gZn2i6I-4A%%l@0|;u~y`QuxL@8=S0qb8(#F|G`a4P#k&dsAU5sNT0Tme9& zj1M>Dh*KOq92{qZ|49137x({q4F3;D_y5Ju0fB?4*W{Z_6|J?tc=G}uanzn^s+1`~ GL;eq?CZWUt literal 0 HcmV?d00001 diff --git a/documentation/images/grub2_menu.png b/documentation/images/grub2_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..69e1457d49b9e8de4abaf373aea435b502929b62 GIT binary patch literal 3089 zcmeHJYfw{37LMZJtPH5@XnbMD(Xmz$VR$RZU3n}j0wX9Wh>>ytF+$`aL3!L66r%!W z6fsED6uuAw0Ynot(W^%B5g@COfI&z>ga9D~gpk+0w>Q>qO>Ncw+`s FIZNjd2n5@0TLZ!g1S^z4nAtwl%CaK!>w_#XBRxFGkHBqPK5QYg61RkG zArKlEHfY>87XIBYJ9Y(Hu&k^M08mCCB>IaYE&MM>x9&|R5bQ)>#*A0gyT1|$Hs`km zY}u71*OUuVl&=>B7Fw^{>8!NAo8u=UZ?SIq>F+2>RPp4-y9-;aXlb)GVAyW3*>1Ed zVs}l*n{ZkT%{r>TS9~+%9OJJ XD(r zF{A~r0F;9ymB_B1Q&E*GU*(JHt61@XIGQ^}<}D+ihZj@wr-sNuU~lGceZo+@Z;EZu zCogCN@8E?@76(4|RI$OBhO@kW2e&}CE-dP~4_4c$fblAi2@~7kd8}#2ppoD q?FKXE_nA_W<#~l>JBJ3*@!t>0AFPB(>(_j*Ih+tCn1V{ta-8 zLg8hsLkCD0neH|)pxY?Pwr@^~Gc2}-2P8$mfgyXkqP=Uuoe!5Fk!m72GN%LRhLa r$9yVAAZ0#=a2@~z qKLgWL zI9iE81+c*fdU6S;N&qBro#uP*H<(RmRF>TSv!@S`8~7VZAd6Y)kB`H~$zr?5Agua8 z(QDG1trN)7_orS;W3L}`FKU1OPy8CnaHbudykTJUre>8i^U4w;eCeB0VO2r_nm%Sw z{k#EaG}8K}*nK^8P7fCgykINnTVoNVfnlVWeYAr*+C}g4-#_xKU@eXPF1YRVL40_W zT$bw9U)T?6zi6R53)c||ba>nWm#OEQ6jb6%SPmi#bV-ls#uS{5lgAQ9sWjm@4b}$@ zDe0)K1o6o8R;d(OOqD SMpC)>Nz{__JIBSk; z0N*br3Q|3ZS+lW27)8Apo$Sg6_i5*i0Y};Q&UNLKxK9g$25K#*n^#48Dz*VstdG zsa_k`>cnfSK^Yy$BLAtm+Sf6hd8@%5_bUY;OieZ#s6-Jq4-?__{6USg4PeWVbFgsX zEa25C%W$0lshER_9>|}KIhk?2gRZV0=>`L8a1nzW@c464-8n#DN+W6E!ttI0BsdS> zjRonPUeSBOg)i6fdMyA%%NCbsm8r?g@#CXspj3;iiM8;{6&ITDQU;WaIhflmXF^FB zMF<+c%qW<{W>Ag06F-r|bxwYt7{3PKTmSJDzJ}my7X1GY;iAz}9!@U!-@=hVuPb*; z)3B~B5&MuL>cm~vigxr~hc2{RDGXV$|7K5mg`uuG7G_(QRB>D)mDy$Fu*=aQ%)d>J z`0T6bN#BBJ 4T;SK2yxd4sLLjcjb={2lMz|KR&vx8hy#HP_uh9Lv$< zq)CSAL MrqdBt7sV|YsXo%05oWJ?>Hhp^lG=T&|899Zb2?iT{DS>t zs!L(Cnbxz~nOqNn|H_27Bl*#oXT4*s(=BPf0wz7aZnydH%y!e_5waK!IM88q<< zQG>;`b 2$(t(7#i P?nsU3g6zgrH78s?QB9~r1 z f8I_1IS*r)C rLtJ9HvT#HLld4ln3%pT4Rxa@H>Pn=WZHkT{kLTBYS%FB&@VEz9N^&ES@;z z=;^5UJ`mr^)tc5kiLEs4=`AdVM%g&F+TAyW+4>=At#BvqgokvYc{MYF0Dc!nV!(E3 z%|83os?2cIY!7_R@QCk&T=~e5A`#$Gm@;$h{- 3v5+}})L)d_*% z1TFZcrb7|O5$uZHR-0Hiam4Tt(QBiZV%N-&k*4Y=vxguJ@FOpTX`6>jWOo@MYI5uo zybyk5*WBBN>SZq?8QJ }`oH2VH#X~Eb%9J*b$h~gMyR;fKvg@2%XIONIcyBWI1LaM1vT{>n-$hP5 pAYA`Qmb(1eDu25&RP+#;v23aHGArfGOO|$>uq`k&fa`Z4|6dhPtxx~} literal 0 HcmV?d00001 diff --git a/documentation/kernel.md b/documentation/kernel.md index 6b866788..9419d443 100644 --- a/documentation/kernel.md +++ b/documentation/kernel.md @@ -1,6 +1,12 @@ # Kernel Version + Linux kernel version used for supported boards.
+Default kernel tree: 6.1 LTS | Board | Version | |-------|---------| -| Raspberry Pi (3&4) | 5.15.x | +| Raspberry Pi 3 | 6.1.47 | +| Raspberry Pi 4 | 6.1.47 | +| Open Virtual Appliance | 6.1.47 | +| Generic x86-64 | 6.1.47 | + diff --git a/documentation/python-packages.md b/documentation/python-packages.md deleted file mode 100644 index 68aa8637..00000000 --- a/documentation/python-packages.md +++ /dev/null @@ -1,127 +0,0 @@ -# Python 3.8 - -## Default installed Python libraries - -The following Python libraries are installed when Mycroft has been fully booted and configured; - -Package Version ------------------------- --------- -adapt-parser 0.3.4 -appdirs 1.4.3 -arrow 0.15.2 -asn1crypto 1.2.0 -astral 1.4 -beautifulsoup4 4.8.1 -bs4 0.0.1 -cachetools 2.1.0 -casttube 0.2.0 -certifi 2019.9.11 -cffi 1.13.1 -chardet 3.0.4 -Click 7.0 -colorama 0.4.1 -colorzero 1.1 -configshell-fb 1.1.18 -coverage 4.5.1 -coveralls 1.5.1 -cryptography 2.8 -daemonize 2.5.0 -ddg3 0.6.6 -Deprecated 1.2.3 -docopt 0.6.2 -fann2 1.0.7 -fasteners 0.14.1 -feedparser 5.2.1 -gitdb2 2.0.4 -GitPython 2.1.11 -google-api-python-client 1.6.4 -google-auth 1.5.1 -google-auth-httplib2 0.0.3 -gpiozero 1.4.1 -gTTS 2.0.4 -gTTS-token 1.1.3 -holidays 0.9.10 -httplib2 0.14.0 -humanhash3 0.0.6 -idna 2.7 -ifaddr 0.1.4 -importlib-metadata 1.2.0 -inflect 3.0.2 -inflection 0.3.1 -ipaddress 1.0.23 -jaraco.itertools 4.4.2 -lazy 1.4 -lxml 4.4.1 -monotonic 1.5 -more-itertools 8.0.2 -msk 0.3.14 -msm 0.8.3 -multi-key-dict 2.0.3 -mycroft-core 19.8.4 -netaddr 0.7.19 -num2words 0.5.10 -oauth2client 4.1.3 -oauthlib 3.1.0 -olefile 0.46 -padaos 0.1.9 -padatious 0.4.6 -pako 0.2.3 -pep8 1.7.0 -petact 0.1.2 -Pillow 6.2.1 -pip 19.3.1 -pocketsphinx 0.1.0 -precise-runner 0.2.1 -protobuf 3.9.1 -psutil 5.2.1 -pulsectl 17.7.4 -py-mplayer 0.1 -pyalsaaudio 0.8.2 -pyasn1 0.4.7 -pyasn1-modules 0.2.7 -PyAudio 0.2.11 -PyChromecast 3.2.2 -pyCLI 2.0.3 -pycparser 2.19 -pycrypto 2.6.1 -pyee 5.0.0 -PyGithub 1.43.2 -pyjokes 0.5.0 -PyJWT 1.6.4 -pyOpenSSL 19.1.0 -pyowm 2.6.1 -pyparsing 2.4.2 -pyserial 3.0 -python-dateutil 2.7.5 -python-vlc 1.1.2 -pytz 2017.2 -pyusb 1.0.0 -PyYAML 5.1.2 -requests 2.20.0 -requests-futures 0.9.5 -rsa 4.0 -setuptools 41.4.0 -sgmllib3k 1.0.0 -six 1.13.0 -smmap2 2.0.4 -soupsieve 1.9.4 -source 1.2.0 -SpeechRecognition 3.8.1 -spidev 3.4 -texttable 1.6.2 -tornado 6.0.3 -tzlocal 1.3 -uritemplate 3.0.0 -urllib3 1.24.2 -urwid 2.0.1 -uuid 1.30 -websocket-client 0.54.0 -wikipedia 1.4.0 -wolframalpha 3.0 -wrapt 1.11.2 -xmlrunner 1.7.7 -xmltodict 0.12.0 -xxhash 1.2.0 -zeroconf 0.23.0 -zipp 0.6.0 - diff --git a/documentation/roadmap.md b/documentation/roadmap.md deleted file mode 100644 index 95b74b24..00000000 --- a/documentation/roadmap.md +++ /dev/null @@ -1,150 +0,0 @@ ---------------------------------------- -**MycroftOS - Version 0.1.0 - alpha 8** - -ChangeLog: - -- ~~Ondemand governor for both RPI3 and 4 (instead of performance)~~ [DONE] -- ~~Fix: MPV not compiling because of missing LD stuff~~ [DONE] -- ~~Update to latest LTS kernel and drivers / firmwares~~ [DONE] -- ~~Update to latest LTS buildroot (20.02.1)~~ [DONE] -- ~~Update to latest Mycroft version and dependencies~~ [DONE] -- ~~Addition of additional packages for the near future~~ [DONE] - * ~~OpenCV~~ [DONE] - * ~~espeak~~ [DONE] - * ~~Python-Numpy~~ [DONE] - * ~~Motion~~ [DONE] - * ~~Mosquitto~~ [DONE] - * ~~Squeezelite~~ [DONE] -- ~~Add the last bits of the LAN-MAC address to the hostname~~ [DONE] -- ~~Update spotifyd to latest 0.2.24 version~~ [DONE] -- ~~Update snapcast to latest 0.19.0 version~~ [DONE] -- ~~Update respeaker driver to latest dev version.~~ [DONE] -- ~~More microphone support~~ [DONE] - * ~~PS3 Eye~~ [DONE] -- ~~Cleanup buildroot:~~ [DONE] - * ~~rootfs default overlay seperate~~ [DONE] - * ~~device specific overlays~~ [DONE] -- ~~Look into animating the boot splash screen, showing progress during boot~~ [DONE] - * ~~Add and implement psplash~~ [DONE] - * ~~Update all services to update psplash~~ [DONE] -- ~~Change the wording on the splash screens;~~ [DONE (Removed)] - * ~~Safe to reboot -> Safe to reboot / Rebootig now~~ [DONE (Removed)] - * ~~Safe to poweroff -> Safe to poweroff / Powering off~~ [DONE (Removed)] -- ~~Make use of systemd preset files (/usr/lib/systemd/system-preset/- .preset)~~ [DONE] - * ~~wpa_supplicant@wlan0.service~~ [DONE] - * ~~wpa_supplicant@ap0.service~~ [DONE] - * ~~Enable any other mycroftos services that needs to be enabled by default~~ [DONE] - * ~~Remove all systemd (enabled) symlinks in the external packages~~ [DONE] - * ~~Disable any newly installed service by default. (/usr/lib/systemd/system-preset/99-default.preset)~~ [DONE] - * ~~wpa_supplicant systemd file can now be placed in rootfs-overlay / patch to be removed~~ [DONE] -- ~~Fix python-speechrecognition package. Do not copy flac binaries~~ [DONE] - - -TODO: - -WiFi: -- WiFi does not come to life after setup with new 2020.02.1 version (found cause: see systemd preset task above) -- Add 5G support to the wifi system (Country setting most likely) - -Enclosure: -- Implement initial framebuffer drawing GUI - * Look into showing the pairing code on the HDMI as well (look at mycroft's system) - * Look into showing the IP address on the HDMI as well (look at mycroft's system) - * Look into combining the wifi code, the framebuffer code and the enclosure code into one system. -- Move over / Integrated the WiFi setup into the Enclosure code. - * Change WifiSetup splash; MycroftOS-Setup -> MycroftOS-WiFiSetup - * Have a look at the wifi scan to exclude non real SSID (“ID List”) - * Figure out how to make the wifi password box to be able to show password (eye icon) -- Enclosure code for enabling services, halt, reboot, etc -- Enclosure code for pulseaudio control (volume mostly) - -System: -- Systemd notify and Watchdog support to make starting/stopping/restarting and failures way more robust. [WIP] -- Enable (hardware) watchdog support. -- Include changing the hostname from the MycroftOS settings skill without messing up above MAC addition. -- Look into the msm error/warning "no package manager found" (there is none, but just handle the warning) -- Included volume skill can't be updated - * Should be changed to pulseaudio anyway, but... - * Check if the included volume-skill can be updated, via offical git commits -- Avahi zero config publish to be set up (pulseaudio, mpd, snapcast, etc.) -- MycroftOS settings skill to be able to setup smart speaker services / software -- VLC Framebuffer video playing support (if not accelerated, check omxplayer but needs to be created as audio backend within mycroft) -- Add and make configurable, where sound output has to go; - * BT Speaker (A2DP) normal (Use a bluetooth speaker as output) - * Bluetooth mic/speaker combo support using HSP (use headsets as input/output for Mycroft) - * Airplay (example: SONOS) using module-raop-discover and module-raop-sink of PulseAudio - * Autoconnect trusted BT devices as soon as it sees them using: module-switch-on-connect from PulseAudio - -Documentation: -- Change README with all new changes [WIP] -- Update / Complete "documentation" folder and docs - * Building.md - * Boards.md - * Kernel.md - * Python-packages.md -- Instructions / Wiki for most common and different aspects and functions; - * Installation - * First run - * Configuration - - Smart speaker functions - - System Services - * Spotify setup - * Squeezelite setup - * Snapcast Client/Server setup - * Bluetooth speaker output setup - * Airplay speaker output setup - -Cleanup & Maintenance: -- Fix / Check all Buildroot package dependencies (SELECT and DEPENDS references within Config.in) -- Cleanup buildroot config file - * remove / disable any unused packages that might have slipped in while testing / debugging / etc. -- Make sure all Skills from the market can install (python dependencies either available or pre-installed) - - ---------------------------------------- -**MycroftOS - Version 1.0.0** - -TODO: - -- Add an first initial GUI system just as Mycroft.ai (QT5) - -- Cleanup the kernel config - * Remove unused drivers and stuff (DVB and such) - * Separate default config into systeemwide .config - * Board specific configs as overlays - -- Implement easy (OTA) update system (RAUC or SWUpdate, not sure yet) - -- Support for more devices / boards - * OVA (Virtual system - Virtualbox) - - ---------------------------------------- -**MycroftOS - Version 1.1.0** - -- Build precise from source at build time (0.3.0 dev version) - * create buildroot packages for all dependencies. - * create buildroot package for precise-engine & runner - * create buildroot package for wake word modules (including the commodity ones) - * figure out how to give back to the communicty by allowing recording of wake words easily - -- Support for more devices / boards - * Rockchip boards - * ReSpeaker Pro V2 - * Odroid - * X86 / 64 - * etc. / ideas - -- Implement first initial WEB frontend/backend system for configuration and all - * Backend for settings, configuration and update - * Backend pulseaudio control (Already available project as quick fix, but needs to integrate with MycroftOS system) - * Frontend for possibly accelerated browser hooking into the Mycroft GUI - -- 64bit support for RPI3 ~~and RPI4~~ [WIP] - -- More hardware/microphone support - * Google-AIY - * Kinect-360 - -- ReSpeaker Mycroft LED pattern which is blue-isch and looks like the logo of Mycroft - From 5f7c42b705e7616c5db42fcca021faeb5e1a44c6 Mon Sep 17 00:00:00 2001 From: Peter Steenbergen Date: Thu, 31 Aug 2023 11:01:22 +0200 Subject: [PATCH 02/10] Remove double boot section --- documentation/architecture.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/documentation/architecture.md b/documentation/architecture.md index d04e3443..f579c85a 100644 --- a/documentation/architecture.md +++ b/documentation/architecture.md @@ -11,10 +11,6 @@ A synergy with the boot loader is necessary, because the boot loader must decide A seperate overlay partition for all changeable files is used to make the userspace system read/write. This seperate partition can be overlayed over either active rootfs partitions, being it slot A or slot B. A factory reset can therefor also being easliy obtained by resetting that overlay partition. It will then again start with the files shipped within the read only squashfs partition. All docker containers and OVOS framework associated configuration files are stored with the users HOME directory which again is a seperate partition at the end of the disk which is also auto extended over the full size of the disk at boot. This is done based on the availability of free unused disk space at boot. (Any boot, being it the first or any consecutive boot) -## Boot system - -The system uses UEFI boot stubs to launch the GRUB2 boot loader. The GRUB2 bootloader takes care of booting the active system partition or can be used to boot into rescue mode for both these system partitions. - ## Partition layout The partition table is written using GPT where possible. Boards/ systems that do not (yet) support GPT, a hybrid system is used. MBR to be able to boot from the ESP bootable partion and from there on GPT takes over again. From 4f0949c3a2d1dabb383d34cc8e57a25889ac96bc Mon Sep 17 00:00:00 2001 From: Peter Steenbergen Date: Thu, 31 Aug 2023 11:05:33 +0200 Subject: [PATCH 03/10] Fixes within the noards supported section --- documentation/boards.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/documentation/boards.md b/documentation/boards.md index 5a5e6d06..a44c7b5a 100644 --- a/documentation/boards.md +++ b/documentation/boards.md @@ -2,8 +2,6 @@ ## Supported Hardware: -### Raspberry Pi - | Device | Status | Board | Supported | |--------|-----------|-----------|-----------| | Raspberry Pi 3 B/B+ | Works | rpi3_64 | Work In Progress | @@ -16,12 +14,12 @@ ### Raspberry Pi -| Device | Status | Board | Supported | -|--------|-----------|-----------|-----------| -| Raspberry Pi A+/B/B+ | Unknown, most likely under powered | N/A | NO | -| Raspberry Pi Zero | Unknown, most likely under powered | N/A | NO | -| Raspberry Pi Zero W | Unknown, most likely under powered | N/A | NO | -| Raspberry Pi 2 B | Unknown, could possibly work | N/A | YES | +| Device | Status | Board | +|--------|-----------|-----------| +| Raspberry Pi A+/B/B+ | Unknown, most likely under powered | N/A | +| Raspberry Pi Zero | Unknown, most likely under powered | N/A | +| Raspberry Pi Zero W | Unknown, most likely under powered | N/A | +| Raspberry Pi 2 B | Unknown, could possibly work | Not available yet | ### Hardkernel From 7a2a52540df05027b076df18a5405af63b519db7 Mon Sep 17 00:00:00 2001 From: Peter Steenbergen Date: Thu, 31 Aug 2023 11:07:39 +0200 Subject: [PATCH 04/10] Add forgottedn Mark 1 & 2 devices --- documentation/boards.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/documentation/boards.md b/documentation/boards.md index a44c7b5a..55b6ef85 100644 --- a/documentation/boards.md +++ b/documentation/boards.md @@ -8,6 +8,9 @@ | Raspberry Pi 4 | Works | rpi4_64 | YES | | Open Virtual Appliance (QEMU, VirtualBox, VMWare, Proxmox, etc)| Works | ova_64 | YES | | Generic x86-64 (Intel NUC's) | Works | x86_64 | Work In Progress | +| Mark - 1 | Works | rpi3_64 | Work In Progress | +| Mark - 2 (Dev kit) | Works | rpi4_64 | Work In Progress | +| Mark - 2 (Consumer device)| Works | rpi4_64 | Work In Progress |
## Unsupported for now, but (perhaps) possible in the future From 5f512fe370cdcf402158ce03192fbfd85d86b540 Mon Sep 17 00:00:00 2001 From: Peter SteenbergenDate: Thu, 31 Aug 2023 11:42:18 +0200 Subject: [PATCH 05/10] Add first pass on updating to features section --- documentation/features.md | 46 ++++++++++++++++++ .../images/swupdate_web_interface.png | Bin 0 -> 1234351 bytes 2 files changed, 46 insertions(+) create mode 100644 documentation/features.md create mode 100644 documentation/images/swupdate_web_interface.png diff --git a/documentation/features.md b/documentation/features.md new file mode 100644 index 00000000..151ee2de --- /dev/null +++ b/documentation/features.md @@ -0,0 +1,46 @@ +# Technical features and capabilities + +## Updating the system + +The system is using the SWUpdate system to seamlessly update and switch between Slot-A and Slot-B. An firmware update file basically contains a new version of the rootfs but can also include seperate files for either the overlay partion or even to update files wihin the HOME partition/ directory if required. +SWupdate files are using the .swu extension (SoftWare Update) and are basically CPIO images that can contain one or multiple rootfs images and/ or files. In addition, it also contain a sw-description file with meta information about the update. + +A visual representation of this CPIO image looks like this: + +```text +------------------------- +| CPIO Header | +------------------------- +| SW-Description | +------------------------- +| ROOTFS | +| | +------------------------- +... +------------------------- +| OPTIONAL: | +| Any files | +------------------------- +``` + +The SW-Description contains information about supported hardware and software. This way it is NOT possible to use an OVA firmware update file on for instance a Raspberry Pi device. + +Updates can be applied by using the following multiple methods: +- From USB drive connected with a firmware .swu file. +- Uploading a firmware .swu file to the device using a on-device webpage (more on that method below). +- Downloading a firmware .swu file from a webserver +- Push/Pull from a fleet management server using Hawkbit. (Planned for stable updates in the future) + + +### Streaminig updates + +Because we make use of a mirrored Slot A/B update architecture and therefor it will always be possible to boot into the other Slot and/ or recovery mode, updates are streamingly applied. Therefor no additional free space is required to first upload/download the firmware update image to the device. The update is applied as it is being uploaded/ downloaded. + +### On-device webbased updates + +If you browse to your device with a webbrowser pointing toward port 8080 (Example; http://192.168.16.144:8080/ ) you will be greeted by a simple webpage that can be used to update your system. + +![Update Webserver](./images/swupdate_web_interface.png) + +Either drag and drop a firmware update .swu file or click the box to browse to the firmware update .swu to start the update process. The progress bar shows the update status, however if you would like to see more verbose output you can open/ extend the messages box aqt the bottom of the page. +When everything went right, your device will reboot into the other updated slot. Fall over mechanisms are in place. If it can not boot into the just update system slot, it will revert back and boot into the old system slot. \ No newline at end of file diff --git a/documentation/images/swupdate_web_interface.png b/documentation/images/swupdate_web_interface.png new file mode 100644 index 0000000000000000000000000000000000000000..9450fe4178acdf652acf71662ac90ca8177b8220 GIT binary patch literal 1234351 zcmd42V{|6n);1d3Ham959ox2ZCmq|i-Rao5W81cEJ006Tz2Ecf{qApkzt0%wN39xb z)vCF!s(H;duUTVMgrd9zA{-tZ2nYzGl%%LK2ncxd-y;kL?C*$^H~Guo6R4B2gfK|e z6v4^g4uqMIoDc{|Z5;eN0P=4i)?QM}2?PYG|6d2_uwBVd5Rk7zDN!L+cm4AZ=oX4q zH6nzoF_+uP7uU<|sm*!T`OO3g^hAnpiXc)X;7BWEEB?JX7hknK9K9=sJ#)}d_@Wq+ zl9IwOhf?V)e`n8gyKQGqbyBHUy>7cLw{G(B<;RQfy?wIyReD`=tF^mcbUv kB!(;Pd-1z0oLGSR z^U!AR{P**R*}#!PMDjK_#A)525B{J)yO{Mk>et<`=SB(9%!i-<0X@5oZbJRSF5T0W z^F`|5uKm7ZCc1g{t&85}Xh33%@-Z%=`745pe_Lwee;@0(9f&~Djdjx5KETwi-|@7+ zcTy@p)?AY83H))_0hfFn|<=BE8Gr#_GQJ ze-7BpO8l?a-eo+dcxx5a^ceN^Na?Wtg)uHqb+}$!MsE9|Cog=3cm97^&QfaH+hZ3^ zr b2iR%EN5k5dnqa7#}yXntCYp%xhyY4hP^P9H) zGyb1PdY$^~r)tvIWw*%9pgm}T(Th8Qelct&nXu2+YqFc->8P(aDF>S)p9hJ7t~mRB zg>44?RP^rK8rjKzY+QveRiidPM0Isgm-aol$KMT@+^l>@_PJ)P)yIaP-y^3oS&IJt z8Ya0K8MO>|(`pAjpy1n8pYg3hg6R$Pr0hA~N7u-~rj1Mi;$z|H1%~@@%=aHBb>f{8 zVGwu7dD|zf=%Q|h&af*@MBV7$yy6ckY*M=({#dR0k^Mim|I(mxrW1c4A_NHrsuOGo zGJA+BoTps_CW3~cX>b(M;cIBh_8+T0ZwsB`@5daqTgf~?P4iI&o#5MB6SwB)u8aXr zEwof6@vmHJ9fuoj;Iy~k`!3+-WIt;YUVwb*t9k0tC0GP7(TJtvo1gG|ZZ-#l$FIEp zqZfaWrzy(q)57fEan{9ficY*n^QuN_ 21znRX`}Ty-GMJF}41At-+>idEzbscDnG@qV zwhrpTmE2llicDr^m#69mt85{2Lp1+)q}$1H*S3yq|H*rv#}=snn!+D=vN<}cy8Igx zBE;<^x_TYzlr}?yHH=6Cv#a1fj}g{n-1!=L)`NpqA@ZLx{9PAtdY{WilhrOw)rt!8 z1fRdCQ+2!EXQ>AL{BFc5?gYp=bn7LJZ;u96{7$U@*|KJvi{$pUt9Jt 8(lcn_vt8>>(2y?yG8K%eV9|xVGU29!>pzVQYK+D)gj!HHeNW zCfRmNRSg%cMh4n}y53~A7}W~>(aT%fiP8Gf|HD9d0aDiwS2KLJ8z-apK^*Lz=TTzx zrUr5bgN^6-vz%~mLTUcDd87GixBocq3$hK#!S`5SsSQh7pZgo?PdMsox$X<`S`VeX z3G99=kPYOAh`15QDn3rguE)mkyEb$KS!!aE2e`J28JSbETk#ho7m>UzWI_z$cv=0y zncrPn?Q=FpRvs{U$HUX??Hb<_X04LzFtMvKX|=Lq67}2m_UegIlqL>GLTN8wKT uH1fwcX$rlt@4;M*jLif2xY-`6|-4&TL9` z((lK?nkaeH8leRZHP;vNV|nk$IYLPX7pH4RqZ7|fQ(HDZeYP?jk(nI&`iE2@Bg^xg zb{f(eNPKk5P6q8(DP8%PfBDueiTm5LQnBA_R(j91XK;9V?ur=g1M-i@9dShZx>Sd7 z(`O!MGy+x#@qZB>*i764XJ75j-_YoE4_CQOioD5idHSs*RsCuUJbBZtCLx(@%4ZqF z%OqlO7%P|oaMs+SVW<0^vFOB2 {^W!p6ZS}qFJL<=iTFQ}A zBn7f8{-AGs&N)I`b Q@j5tjWNlf@44$#7%&}KWq7X) z{-Fzhp%`dHLHpF#da-ASIr13Z8fO}MW-P&tRQ6=b{)wr!y+kFt|N4MW98dCjh%M<| z{x4K)|AWeaf0&8@yYK|m=LSJTZlklS9^NyAih8>-Hm#c1w$(bK@?-C=n5X?8wQz4~ z@zJuPftFCe*LNxdcu|kXAMA7_ mdx=9ylZsZl*IXgUPWdqWhbzb#__q+ zYZu5La;z_wqp@4Td((!A&6J0o^Gt?^P2A?n?~bn_F;P(!@N69u#mJFTRYcMsrjJy| z^w!tqNH_bJk>Xz W$MB6-83Ezz|V2&Nze<0LsRjzljO^6%rGp4?in+MH(Cu&;t%qj zy`0!aeo<&ZU2fX5*ZLf?*tpEHQa2&9)OriOo6uk4U_OoWzUG;ygooxpWmbmsc#752 zW>=5b3o`NFs8XpZi)}P(!w69DFYhr`XSPtgTBGJyJx?yC?0`jgo3tc& pO9)_IG+Wh z{}DT{j}gf1<99+9-8>9iT}l-OSzVpU$ti=&@{!n8vdmxLdB~e|12Wk~nX_L4D*q#M z9LTnAhxeGa#-$Du`CWA1^SjXuzLahxuJ)9!(tCUw==pEJ_vi%Zx4t6EQCfMZKCj;f zcs|*JM*d$`b$V)Naq48F6MM;epI30Hpu=awkngq`8A*AcXx(H?fA$BD7~x|(%Kk** z&bOk@knx?IZFdd-y7%Y0=FuR2GPTsTt! hL~H z5BfcqJ>QZ4ubw+z2cB(V{#FwI*S3LmlC?hgS24c#7=)W?r05qElnxA&2p*i7M%m$^ z`rUl&ZTo1w57G&wQvF*Zw}sAO-|BhL>5Jp){Y!L;TUZGgG(8 UT120 zi2C}7em)GV_7idWk0@3W-)8w6v|k{eh6&F%K}Isw)ayp2a^BWw8(bQP?UG%NRS69L zhWJ;-cQgH8b--%E&VQ8}{~uKf|9>b~3aAf1$m9jf$_5-NXf4r<4X7g+7r2zbNy*q} z8bp!(OOh0+h2f1=QUMsC##EBBc@SS^WEg4#!h=Zj=mdr@&)*`^cJYhLgw>3Hs@p>} z8nf $$W_fH-&?%hbkmeJJk7oeL5XYGchoX zvMRZSfiA@L{l;1Ujyu?m5HI!Olth?K;Ss %lT1+z3a)1#}Jo~o!1XEKnR$p3K$zpJRxaB@{_ZNe}=e|ITg^yIk zz+uGc)yHbF?-dh&HP+jvs7MT62=Q4u-Y~F=HoYuan!=uim-jmtv-9J|%V75N7U#wn zXZMpsGiELk`D`Uu1e-bdt2!Kql(Sll(X~9OG3O$gwU| Ummcn zVORzAmQ$R6KFW;lbZL3hb9Y6`%8}xTDqd0;zD~v&M%FZDPf{dJk!3Y05=~_lgI!YC zq@aC9%`!WU9$&qDQPw$<=fdGWJ{B&4D^R#x8=_Dx5ry}-jTnl>6%AndBPn@v`0f|< zTzG!ToSG2TvZYHnbjWIQKv4D(oi%#_)mv;x0$*Z~!A}*)U x`s9KO zKH3x}!nPZHNZ^@AKY2bjlN{T+ElLP=mNvvod6`A358r0}ol4S{@U-Al8Y^~4;M5{| zBg1=PmfMv9+RcOrlX+WdICJ!xw*LET^;b%U+x^FTnC}TbGGAVX>(&VHojG>q7gyi0 z3 *$2?>FC#IIPvIJkX1HK=;xU(=r> zeRf}IsoIG?V{J2nW9ow7)GFGc%)KS!7i+w(%f3F|$G3gLXR9iE=MAZvs^ki(iq7|y z49;0Us&xSE5%V!dg*6uEL(Lms4`IX@)B36itU|M3K3O D||SPf&M9^pjzX zs*`e24sj{R9_zHLt(jB37=5vncm>F_6Y>fePU>Ghxqw3e2s5QljHipos6}J46 Vc5c>d1blH4S{(6i+h+Pg(*X|!M7?c)`j3(M->&EQMfz}< zB{r Ox7lt*c>gm1& z63M2)RmJcWfk! lp7ZPwDmBl2eq|Uu+tJaDtpHana z^DG%uxLHkIAjb?@S<-Fg=R4F@RDcdMh=a)QJr7=OZBDHOp=J o~1lN2zwgIxIo0SVR|`qfOpkaYH6bj1MwoCL|mTto@h*m z0f+8 0EhN!|x6L zE=JU0&kHHG`_Ajp`w`x(`*lYp(x@zciA^WQy#&+tX5i44<*Q!cz9@+Epy(*0`=dQ4 zQ-_g8odM30ngEL|n5gGvFfvvN#l5}R=3^(WWAHA4$$Pgv=e?XMsohgm&Z S*(tf7kh|3mG`Do#8LJtPizQdAV)#&f<(;pjc zG5AdS+0TszZ%kchQqLfC`NI)!aent <4`%!h2Q&F()#21s(aDzd7N4)8G~WpB z0mtlO#}Nb2Igv$lGo*{rx#(?Teh3@D^{e*)Vq2c6<*z?XK}k{yOnIb((ofL72L=u5 z+J5h0U(GXEV#=x*I% 9i{f3Z+hFWRz2poGGV@! zuY4OW8Z5>XjR^WkOJNCE5ft!^#netC>+&G-S`xmAjm*D$IODTy%19xO#W4}m>1i0EIx@PBY3L?zXM z@uY+wW&1*rAf?@i(a9MQIbDOIgjVQT3ev|^<&FR-N&UEg0G`=Zks!&x?n~|+l`Vb| zt{N69g+@ArSE-BO)0Wd_6SnIu`Vc=Chkd=<4W3A;u{uz$njk)3Wy%D8eS^mtJK;Y$ zU1Bc){V6=E1(%vYY^qw|73oqVm<#Dt2+Jo4wk;cJ&l23ymOpeo=n1wG!V!;}$w)sR zcn>j`IOki}``cvqw;EgOg!EQTj=BW#gtp4@NdNLRt;~h>82SqUT2~|sK~`sy?nErD zibp&Uk;GG0G-dH_*3VA2V(KGoTNOycg*=q_u6vk6+lS_k0Jgg-d4$~EMRW5_%Pt)^ z^X_O&Y9n8MN5fPyPK8z3p{mHR0dxeAa4PJUK}HT67(of_HH-=waSACCA?I-c!!!;W zMCGg(Jm_5+H2ia74@Qsf4^pHKL( n1T7dWH(C%T1YJX)j=V`!yM7TP9Qr~clCl#uFJBQ; z{M(E*nW!2>C|J3kBl^|Q&8(gdCI5%vme3uVgd9Sy3?v7vdbA=;9V`F~#KB_Mh0o$R zKCPs+FtFX_EjBGGp)$mh$Q?WT_bY;y6h#Qh4RTi=#3k{s0dTe+)R>z{TP-E@8h^fT z5@eE(#nu>}g3B(^=&k|QFcXR>q2`!AFi~P+w*)I%M)-+9l9l7j(;se+^hV%2pg0&M z0T$`8`+=BXJ ODB_*0hvfXEQ}P_+Q oaZEimr^F*n}}xLX=E#L zqB3Mcl#HRL?l(S#k5@a~E;KIo+#C|6H}TN3hab%7&p<->pwDbyb7LNBm+qI##xqX7 zCmz2Nj!kxa@yj*8yJCSG8thAmfFBT%CC()!o4#jV>$cO?6|%%Xy#LhaNE}e0sT_>; z#qAd6wIDVWLxm4|E6ofDik+|2*(^`RXZIG&^51RLMjXYJK7eGS-KZ7ln3u<=z9`-_ z7SLgPpY9WHc2rKI?bXL+dw%)7xHx(1IT%tKoY1a7k>PeSiD(!~(AADGSY>3q<`$PiqCaaNI79G;Vgm?p{W+!gm}IlA81bx@tE}2U zEU=)YDu3iaRQ?$gu2jk?XXJb@IRqn<=pxQ#Laa^_4M?Fg($p$Kl- W z(U`?7KicrVAC;JH@!zv#TT$~^=UZnu4kabxnRowbBz z8~##|qr|OBfzbu^G%X~IsUc=wqDF2_A!J_4456OtOeH=Vaa)x!e0@(A9ZMp8?hVSt zzkmt7#a`T)sowZ2Cukd6-cJVKoT`&i+%-ITK*<_(OZ3 It&|Qa5C#|soH|Ov9=fnWwA$y*4Q3*9R-Io^=cS@{ak1N|bD6wO z_nuvn;}~Ft@dz;8&?Nbs1D~xET@1cK%Vz-nHFZJ~ZRD 0_kdG(MQ_EP2k6?GW^sv-^ zxqf@(_lkYQ$Z#LGjna@}7@&yiuaXHNv;!aj8N^Gk^Laxge(r6~M;CZ%W%AxrF*vzA z3BtVdA)bNhLHz^I0S`3^5{1T*R#e;2(BQRfi!*hU?S*7c#DWk^>`Lwb5aa*Vi&jyM zR0F9QQCqCzSyjHEMtgubUSmz|!aK9g!~6YxAVJ{|yjTy{@D0jh sNXu}ah 6>j_!-nS=fAnvTrMQf) (z56s&dr=o?mVenB8@xzElO9;alGJ&2b a%sHYKbpUTKB%Y96_GW`4J=^Ak^DxiPMXE28Uum zSKRKpXC484c1l-NjCWm=Z5hA v|iV#qdfm4Me(^r2Soa G5-H#IYNK)7f+yfg42Odffng{fR>Y=vGnmv9iv(+%KugIS zkMbUzX!uU|7@-61eqlk5R+ixD@o~>Nx>iJiudqD*%wy&khA+zUuO6iC-JM?so@k~d zVUA^itA<3W;nugrhHTNth}^7+Bm(jeV!0tu8x%%Sk`c~o$e6o`?adueVcDOXaZ#&9 z_jAk2+Hd9LhN9m4vZEdE&e9>M2?Ebl^XAYyprK&F3XLKMQ|hdQ#Ayj4KWxxh%_F&g zXEUA@;&ahe?!oQq7D;01U-tLC#ACYh4|r%i{eY~TYlN;6NM6bp22<1&!Le)Gv>l8I z%f`B Yb%^AOFko1+>WARO`)5gjOLawy(Oe8Y_V-GdN zV%8Li9;QK{v2Ua{vm|c_M1^6KWtT<&0rx@vDhvWG+SkXm*`?i8@jEj0fB~P>5JxoB zbav5F{Jb#=`P?omyTb1i_@a_hRy@7PDBpObK30WOyZChjFVKuiG1%~MfcHmSO=5`S z^Crhf8AB#I2(=3^QSi#x021vFkOxx8H6N~zeR^H-`rN1Tw6^# %q7q=V~-4-YdD`RF=e0d5^oI%5$4 zzd>X*+C1Sy=A`pO(clVo>lYnAP$*@@YCtYsD$9%E!yyQNjUV-}w%qoEAmlS1lNMH$ zOC31v1dfuVW@ojY$TjPgP1>xsJ8ibPDENKMh6y}`bblOZpdj_$gOz;$9&+%_bPvH6 z!yytg1}V?bwstY&N~as}G5`x+ O78`)H8nmoe$2+JkU E0{Hf1oR+MTyK!Si%|*(*b!WH-t7#%UFp{YWSG0%|BM@S-7ov8@VTL;!c>a0mNE fqYWCZC;5<}A7RJRt%PCEZnvaT7xodPvNr}zL_WL}TJCV7Fc*$Kuv1#sZr>n+| znx8jU)-d^L_;X|ayh-1plXN7ZNWhp_ud~0!?7y=HA%-I(u ze?8yQg$3r_vwqVN+=yMYX9jcRTdcES*NhyS&LZLfAfocf^A2dbRtU_VeF!&!^1R(V z>|2eXq1z_(9DBF+>ZmUNHeinZD`-vMBDv9#d&w*7PkI4uUq~M6a{z0`^yE<@h0NV~ z2eT23A~=$00oA^Uo*DzUiAHSW_dV+XYT*UB%52VbNY*LRE_IM A4P{Wnq=C9z(Y18;O%L;oLjH$^)}DR; z)a*2`+tPXT6v} 942=TfJH;C|P3$YV<9} ziTb)W(&or^qZxhwdRHPlHO)YM#Uhv$C*8lp9N!w#UdgihAPmXM7vO7ZidWpP46Nj$ zrh )I>Zw7ql2JEmqWq93fuX*!bMV+e`iMHX-XqnR1Jygk~PBCovEVZsIGI( z`~|uh9245ukJ_ySkLPl3?<%M=+iyvFwPXdnvdTn;rl+_Jvo}K24n4&{G?fIS>K!Fh zkRmzCv^L2*bc}MEA0Kz&l5Igf`9?zU93mKzQMA^y*Oc`9g9)Uc(wLkBgM49JSg0dr z*9e|9%w7ap7Q_KEnKDpfw3n>jrUbPpSx+KC%z%t)zh$&4_YMqTz$&YG+v8G6FhyZn zC;}Fxh!>6kM+pG`=KnYgGKXF(`%FKE{xFN`? j=BhwqEdy_&KH&3IGX3Q?Y9!Vw0SK?(U`V-u^&!#0*(L{o#4HXG5pT|`} zz*CazS8>HPE#Qgg*;x|H)#WK2K?AMYx|p|kQa+)&Pft2XAlx_NcWr U z>diQ6)VXz6aFyA8hUt4#_;S%ngz;UB8wOb8<4i&yvZnc1b7sFxc_QK3$$^HD#%-~; zTOviFDsDJd73Ii&h4QI%TNK|haUb8i@DbOs@ A`Dtbj(mVPsF_L_M2@FN7FfBbri|4Eu@ic4?PSQ{bmEY?KtLA{mWSE zH-oKzMrCA%bG` =T^u~zI#z7Jw;HLF5pg26jG*6@G8v4V2hF_Ml*0D6%olJ;a9+BD z{Wbxo*R_CL-ff-jdf)lb`Z!)&$h>ytlZ%U1?-w*(a?9T1XjRz4f>CC2c35f=2K7x* zi