diff --git a/automation/Dockerfile b/automation/Dockerfile index b046564..73e9bb6 100644 --- a/automation/Dockerfile +++ b/automation/Dockerfile @@ -14,8 +14,13 @@ RUN rustup install nightly && \ rustup target add thumbv7em-none-eabihf armv7-unknown-linux-gnueabihf && \ rustup component add rustfmt clippy +WORKDIR "/tmp" # RUN cargo install mdbook --no-default-features --features search --vers "^0.4" --locked -RUN curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.34/mdbook-v0.4.34-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory /usr/local/bin +RUN curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.37/mdbook-v0.4.37-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory /usr/local/bin +RUN curl -sSL https://github.com/Michael-F-Bryan/mdbook-linkcheck/releases/latest/download/mdbook-linkcheck.x86_64-unknown-linux-gnu.zip -o mdbook-linkcheck.zip && \ + unzip mdbook-linkcheck.zip && \ + chmod +x mdbook-linkcheck && \ + cp mdbook-linkcheck /usr/local/bin # SSH stuff to allow deployment to doc server RUN adduser --uid 114 jenkins diff --git a/images/satrs-example-dataflow/satrs-example-dataflow.graphml b/images/satrs-example-dataflow/satrs-example-dataflow.graphml new file mode 100644 index 0000000..3384f39 --- /dev/null +++ b/images/satrs-example-dataflow/satrs-example-dataflow.graphml @@ -0,0 +1,991 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Folder 7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Folder 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Folder 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Folder 8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Folder 9 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PUS Stack + + + + + + + + + + Folder 1 + + + + + + + + + + + + + + + + PUS 3 Housekeeping + + + + + + + + + + + PUS 5 Events + + + + + + + + + + + PUS 8 Actions + + + + + + + + + + + PUS 17 Test + + + + + + + + + + + PUS 11 Scheduling + + + + + + + + + + + PUS 1 Verification +Reporter + + + + + + + + + + + + + + + + Application +Components + + + + + + + + + + Folder 3 + + + + + + + + + + + + + + + + ACS Task + + + + + + + + + + + + + + + + TMTC Components + + + + + + + + + + Folder 7 + + + + + + + + + + + + + + + + TM Funnel + + + + + + + + + + + UDP Server + + + + + + + + + + + TCP Server + + + + + + + + + + + TC Source + + + + + + + + + + + PUS Receiver + + + + + + + + + + + + + Client + + + + + + + + + + + Event Manager + + + + + + + + + + + Shared +TMTC Pools + + + + + + + + + + + + + + + + + + + + + + + + + Folder 9 + + + + + + + + + + + + + + + + satrs-example +Data Flow +Diagram + + + + + + + + + + + + + TMTC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Events + + + + + + + + + + + + + + + + + + + + + + + + Function +Interface + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Other +Messages + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/satrs-example-dataflow/satrs-example-dataflow.pdf b/images/satrs-example-dataflow/satrs-example-dataflow.pdf new file mode 100644 index 0000000..a57550d --- /dev/null +++ b/images/satrs-example-dataflow/satrs-example-dataflow.pdf @@ -0,0 +1,954 @@ +%PDF-1.4 +%âãÏÓ +1 0 obj + << + /Title () + /Author () + /Subject () + /Keywords () + /Creator (yExport 1.5) + /Producer (org.freehep.graphicsio.pdf.YPDFGraphics2D 1.5) + /CreationDate (D:20240208153304+01'00') + /ModDate (D:20240208153304+01'00') + /Trapped /False + >> +endobj +2 0 obj + << + /Type /Catalog + /Pages 3 0 R + /ViewerPreferences 4 0 R + /OpenAction [5 0 R /Fit] + >> +endobj +4 0 obj + << + /FitWindow true + /CenterWindow false + >> +endobj +5 0 obj + << + /Parent 3 0 R + /Type /Page + /Contents 6 0 R + >> +endobj +6 0 obj + << + /Length 7 0 R + /Filter [/ASCII85Decode /FlateDecode] + >> +stream +GauF[]96a;XrZ`X=6'nI']0G-Xc?4G)r9+Z>EKNG2R4%q0^eCF&Ru6"F&ec4BQ"pOe/h16:(d[p&-0iM +R9opj8<89"/O*Y3#Ch."r:0gdGZObTo#iqpb<5Q:*ns8CKnJ,8':s.;OT9E+^)s8Q;e +r9++WDnl>Ls7O/,aM7WLDu]Utnc/F"n6>@gGouoFD;Jt3gAG(frg14qpF?3tR.eLKCMf1E/rJd]hI+0]Xq54JJRl^sr%oMRkoH[Tc(Fl@8Z9pkV2Z0MAfYO,X[qi%`Gd4bFb +=KSY'48t^Vqiu:fHcg^5au[k`^K@Dm^]*8Q5%E@BWdPcQ*g/,>on`NHfJ,ED%VO=X%VKLU@NFeI&ObCIOn'>/J?L+qW?ZCN,D&FCelSgfg +o6]qNBj>G_ci!"Sph]Qid=+g?lO3Z4)eDqCCc0@ZC7fSIMUeJml=]@ri`D1E24RK,J_.nX#6t4/^9EZc +rI;jB_O\\Z9ejMUa(J^[O+g0#S]bY\^LA;$9,QB$Yh.M$hJr1d%+3EYORTl +5?G>*`353h&-(`NU[`NjB3j'nI.d/rQb]RjVh+%bd&DrNW"^J)TsgI$03"Cj"dNEOg&&Z93'YHW$L'WJ +"(+@_FVHk"]p?q,95tqN^qm3HkfljN7!e#ED5IDBBEJ]9bn@^riKja+$:5-m +p@7540@QMqrVn6G&6GY,?qL3mp%!1k>R>1Q5!sTejfTF!G2.aRruJ0>hd<@(IOW\]m13-f'e/=t>W_q. +g`3*g4')?=.a:.lF:G +D7i?&UX&2+0@@Mg5e4W!B=J,_LC=J&\5=2p'ik7g+pGZfUEgFk-l\:lGq +-lGHD$WN/sBAI)\\E\kLo#6C+gO61SMf_O_Y];u8U]/[@lu*Wuf_SV%::k.]R%PU=PZ_oC-;k-iOq1&F +q<&,*eVn8)/Aj[SkKf:\-.k&$!Ptf$=hP`XZ5P-OnZ3]T0LUfmX#(\AVR$[m-X)SGIQ3ss@kg%U^OEp! +=b"3Cq@=G](k4PNr\LcOeS+$C-SC1p/t>5B!A7$;ld0rWd2)=:.d:FW(et*!V@A'WDZ1VWBdPEqI3k#= +SF;S"CWYcMH=Ut;;/s;Tp@7eJe0;]%F\r)YT2gF68EA5s]k>AHB!7oUp:A;ONYu@PcG??P:to\X26bIC +*5.DL]]KKalNMDml'hL)cX8s!e8p)T_pbQ,[L(<<`'2%@.9fT\l*!q^2gf.`gpf^99V]oAXU[aI#**re +%W087/RA-(EGF,S[CVV[5PD-=OapZq-Rf#LQ+PW51UbKprE:aG5AKC4!'QX +HTiR9.oH.M<;PkSa:[eX:cP#Rs7Q96Ps9C6nDbkGCh/^((ZO<>E7LJN>KH))ksd0D)HQul4d!R%ZVq@6 +[G/UqE0RU<]Pq@dnE4>oOPS0m_e-#9dU*:.>6apsD,rMPki^ef8^(qc]M1q3KcDX_?9Pp20@4ZIO(5#S +lVoBc3qdJ.hAn0WnB(q:(FH55YHLi2G0mkAb5(=P^"68EDE>JIYEMpPg$#0h`Qcl`p'emQ*9dN@G/Eta +Y<@p+b$(gNm!L_2fd0ts+(of\4g`bqqX6L_dQ_$6Mf`Y8B^7/b?,lDs)M4;gbSuhE]%pt.E?6X31*UD$ +HLl?hI>OY,ZYF8!l!7jR]g`)g_LP?r^22hd*d"AOZQ%0)H#nk?*UDPhMJ#PH:`_Ro,o_ha1c)iIq4nH& +qEm?SbYd]@qYsY2VCYu:/sb566b-Re/#4=\kPC:[d/%bJQbU4@r`Ai6J*h\FQSfgGfWt6]#>=DFmH][AHL4Ki+j +r3alA]rn;]IAPhD?J'(aBERAm`h0\HY/dgAd9\tP[U63!XBid%Jb/C`)1J\A^VQdg$m3Ug'bC(1^&A]> +<4I9DJ)7I)kE#5$UW;(pBANG&\AB$-osFm/^VPi^9%Z82LLj#:2`a +CJ;Y"3d0UNa\Z7[IhO$.g/XU:b=!h4EXcM.S+J\o=u3[LDs03rAng;;B>bZMH=QG4)s"#1].`*##0e^r +2gjo.edQqL4pP*JiNiS-PRJl1]euQLp>Q;l6g`7(#6354&Jr]GTe/Z9mAmUp=(e,Z0[8#k57O'U +RGF_Xm:HYhjqg/-n`tMrp1Ntsr4?<^e7-<1,=W/[lD-jSqTup\Mk?iRE]-o8* +UENI=,<#&.M.84gn&^#=b^L.m[#9SRqhng!E(Ymr-1!ej5rtBV@t-SJ ++8Tb'c3p>\KDH""^TamDXDOED>:R\ap[8gMYj+Y;Tc`Uj%_Y0#PA?EnSZC2_Y9"e8Ti/jC-uESb*\D_. +B:c:o6gu.Ye!h2$AGjkfY,YcsA#ob*hBib9oX:rFd@:%CN^&p? +[Lsea6.fapeDFa,_L>#RGJ%Lp3'LZX$=?W8+K6N'#'NiKK@7cA6YkmDPZbFt[uss>O+(BGMY.'Y(;Ph< +S,@YW+pSiMSJ9#Fr&$]._56tr66%*5p3Z^crY@To=T9BhXVpk\?kjU.G497t0qO\fiHqBf\Ot\m^KXt? +86*#&r#K-`.:`g)=S5IJo?q!D`(Fthd7dEoJn=oC' +9l[XKB"cg7WAuon1Ac.#R=dDK=b_!:"YlKs-q43L]e3u%S(]a"NM)5%ebW[7>fW#eY(>cRY(JZ0^P"O" +g3qoo?QJJ#&WugSR%ponqFIaERgt:$'NE4CH$qg>$];,rj_bMG^>s+Dak^^=/h#D5bo0j6g9_&cUC>Kf +>iGqIZ/sP'"\Q6]\B8Y=Y0=Jc`ii)5L$QfPZjt>!1f&bQMTDncqB:5KF$DPKgs;7:^OO:A%B`+rW3Dm? +XML108kk9oLGcTE\ZkVUHYm">n-aCsdjHi@TT'/`-^DrD;LS,NFV+r@UNOc>FYK(Tt1+n_He +kZ>k>%h/;a^Wd#Xq3/P_KGee=%mB[+^L0ImZ,="D[&mW:d6DDRMu:@(ZT^HR:u#a6=s36Ka&UhbJ!9NU +T.!&EUAmIa&4\uBTI&mm-@Ko>Tq\K1Tj(m_>IVp3%"#N.s!rk]d;e&8U)tmdLK6,L>lC<97E`S#*E-b +Dn<5uQFm8_J)AuU,Bn`%9"a!SZBaP23!n?RFXjPs4gN,#%q^d&U(hl#1BkqT:\D3i%pjcnYj;2c[QaDo +FfE-X9>FX-:7cdkR-F-G:V*W`Q>]G=`bU&7Wn:M%-hCm0X..7-Bc-XW`SCd(,]i^-E/#Kh6SaFf4g6)o +SlfqPb$3=YW7"9t=\87G0\]97ai!5mFrUA@L:1YocrSq0fWHiJpWNIYjk?Y: +j=4pA_(iJAN#HBFGCSR4jfcaVs6q%=[_k*i*=#B5Km0'SGQT[A\!Qj^XImt^ERqOt;52SQ`$S +?BTWd$91H8b3nFM]&FFF!g`]XU(=E\l-sF#=SjH^M=WXjh90pbNq(j9G +bDI4@W<`:\[Y/6U[.kKdgBhtQL,$I9=Bm@%-/,2HL0M2@/Pq4%S)6`ing0>]"4nb:[O[uGCGRW`eG>Sa +BN_heLfCgog@HV:ZIV/`Zeb412'^Y5An5P"dpQCIUsHoj=SRg^1Krjl.E[pD+9'H;I4*cTbWaHV2ojJp ++#Ec*0>CMt8r"t`&p2dS]VNs[c]E_tr%tehb3Xa]RoV1g+)OiEhNDQ"V^,lrZ5:QI*p?N4>l\58BF8:L +G\Q8@iMePYg6>PZF45/&8CD=@deEhr9+j945.Xa5']/0"3G@s=X41kCirAQONrmf5h^GnS3(L-Xn +N"boTEQ/;Ec8;6o48pT``!U\lSrYf$1ER&co$:/4*WL1f)]Rtt:7h$8;rkmS_L#9jepk_Hs.;8brB06A +b9Z.uP`Jl!1YXHj#CGR-OTJja=Ct.cUD8#.4I;#gO*ie0l1Gdt(HiilGDj(Y)_D$OGf%N>eh:m$j6^aL2gj/MhrB>P3\dgK^JlHf?BMl*o.+a#U\U.X*q3BMEm'YMGKi>-s*CBa7uJd'@a1**:0_AF4RH` +6r%`2N(1S#8C?j"LJ/V<9#ui%"Y]]j`CjsiYs]poYi9XKbt#EA=IBMrs,NAd&U<%m2!4fY$g41+ATF$2 +bf%D#-2#@00Joq+%eLu$3J8,[<;jTaifYr?\_.Fj?C;cZPq/'YT]):Y5`s/3*95A[`Bh90>HCMYa*a7U +U7?W..tS1WN@ZTTl,F<$%Xdtc#7Z_:+&oELo"iEmaN6U4P,It.T`V4bNsjBW<(?-_:p3U +RScJ7+7fl.A=g)t"Sip[S^u)B$KV4-Dt%O6b$Z5TlcSoQ7JV9X^U4d%,!NYFC*9R(jmTlZA%n/s;/+7q +UHB=GtZ,k_lR3a7qp,^/*Ltdj+BHAQt%.dsNX=3ZSgf_:&aTJ28sQ+%#H.],j9er+6_KStgN3@=ndda\e)EX\ +"KDE0kp@/&8cb6[qJT/4Lkm;IehlZZs,\H0NV42$1lM,n-uAIL32WG&Iu* +;Wg-j]i(Rgr(a0)l1.H;Z'DAs1,C=sTQPOV7+4aX20t[&qfqZBG>+9G1VbLe%'LB>,P4U!?HgSCF`;K, +eEO;P$2=eePregWIf;.WiEdsQU:aC`e&K)F@ZP=Y8WK*gURF[$j0#eg+Dp1%+]"H)r&?qZe#B\eV&?"@r;Y[ +3F^\oq<]Iq3t5TaZjJ[I=XD_AgMEIITK*e^7aSAq>[t7DDmi +ZcpgBl(W(Pj$WGj#r]'U_-M+$b)3%LNZ?qm>onbESb2kJ[52VZpa6obp"@t[N=4'e,!Mb$VADYsFme`B +W:V3%\B0Lp?O==)NKl507^:2BGLW-qJ^(JnMU>0CSf"(YJ'ZG5r^Qfi?4G,hFRu@7IWa"K0uan++H(t- ++E61\:D/)raXM\Gj9X8j#GV!$+7=84g9%#RpuA>l[ncgu)DVOLGt)l@:lS5HY$l[uIHK>rdL*rgVFtDA +0CtlE?leFS?;TZmBangIXNXDkqmpnM)Fl_!8E72q)(84G`fV$f"<=&Q\k85>c95)E]%?(c8CTF`RXH6-ng,i-VIW:j((TH +9]K[F:/g36'KI)_UPOr%rna&t*1`EGcFSd0aYhA[GIq-`M%tK?I;'[1f/T[OF,e)'W,XX5dQ!sc1lgcQ +Sas-u%\?b$[+!sS?*BA$GA%uOE$gS)L`46K?-2cQi9:NMFllj.*@bf/TK41_0J, +Y&Oq(Y&WY5UrF"0`Y%?.3H`?6_=*u]]l)MR`f\J:VlY\SJ%=aa9=H+)rPNp<2%I"q2%DJJ29r=2W,ZG) +cp=;\'W/?13Eknu7?5s8>eBASU\18nXM^4"^Q>3Zm!C@nn;]Y%Mgc`0BX+bbd5i[]3EkV3_fN0p8teE=GjIs\ +94$=_#LU_`Y8j\)8L-01*b8WS)+Zbk_NURiqjofmD_IO#P*3gF"2Z]=lQShlFA\'!@-jGtj)c3PWM][ZP,G&X8S'?IAud5hPK*i,N-k%>(JFl[3Vb\UI3L\:`0Mq5aAT4gmE +++)ZYGs"iLBWN]6m6mAt$sb[F_o80=s)?7PNn/iDl(d!to0OPTVEJ;Qf:+i^r-FKC>cl.HQCN5C+*L)@ +@=s7-eP!MtEr/50a[TXnG5=Wjg@RUE73m'lAQGLHBl.-ALM1o' +48A*(Q5pe\]%X6H^[*MY(L@ll[/YqBic05h99m_B#-4O@V-:d7q6.b+e/'^YhELRH8S?^OO*G,& +r^pYo=0aa_Q)4=kO8+b4/(k=#G$S23jlufXXb/YUV4HHPZYa^)/SqKQq5ZDSA`T>N(r0<_1_?duKH$T8PCECMSY>RU:\3X!GfDVEerKY@J$^k>6q1h#_]iYG!GOncI+r.\k\+%#R;Qf:" +:Cdn24?ScFJ_M&b>i&0E)Z5l[7/8?%)>G`$_i7N`(0P]cDuHSmCe5m';I]AA1jK_YHdI/:Sj8qh]a)f! +VpghVs0H]>o=Sl2RchLdlK;(Q&C9`/q_XkN1@Kdd%Pt__aLqh=#O>hgCd$e22tn@MS_H$j6.6n#]E`;p +ZV*J"r%5SeD%`XgUs<.dd\5G+FJd1UM1$e:q/0a\QQUfq]Y4HdK-s:kQ4l&KGAk8P7a&C!EoC +X40p)%]<3L%pF=eX148YH!7&iiD.):cq3+Z<*S2]5OI.,fl6B\ktgb6l`j)]s$NtHAJ_+`En<$*nu8eq +?0".^McQ*g%iiuDi&G]tH0b,!n2Y[\!Vr5AK/U9(`D#MYNc]=i8'lV0[+:0JFJ8GZ-QIO^e>bW4$)Pj' +*eE*ncu]nrZP72Npmo$SV0V15o,9AS/_S-BLGn7tUXV/;&%QoQ!OW!B#LjU_*o-VR+23Et:M4qOeMfSD +=nm")GK\^b*5%?00M>T`^e@nRF?0,@#UJf0`2rn=6.<(?a3XUCT[Jk<3Dg7CT0\Q&B+p+(KX''EaqV^G"k1(29lQ# +S]XZMM"MQ47L8o4f^`:]ID##Nj0c:Dg=Ls$8#tM]1#1!e\o?dk&)WGf*K$EF*j+uSXCHqu_e+=b%5Q6- +G:#$jODEJs2'26o2Z%*ngME,PC2'8n^r`n$\$X`l,JFC^u1Pr?YfE6SN^d'Z^GSLo4V=l +TRMm(.pp]*<\H$):g +R:cJ)ipA)*-oFb@\hqREGcUG:QMG1V\kW1iNTf1@cHqq!17M^eoL<]/Wq[P0e%F[`(Z.N4gg1EN/:)pR +2YIRQ(<42KpVbK`AFCEi("p2:X'p"*=8LO*L/q(/cFqr/"E%+%)62qe,OXma23`_s7fSZKd+_24om@ui +YR](cUfOFuj/=[^*ZBg/EK+H]&@f`JM>!1U^:gOcBq/>I +S#11;&Qb;aY&T8sEU8-:QRk3=F_Mi-.Es`q^j8bHK)UPFYuBRX$;F!L1Bt6!23+4dGE"BsooWsY+^(__ ++a/j_g=/(ank>$!L=*gpcB(4INPcf8Vm-3(EU:)i.,EB;(E\CO+^M$dVTG5_N[&9Y@VQnP[knTW3&Jq5 +>WGLJF"p%,)c%6fST88/c.@(>Gl"hbjC_\"_+&.D*q"2Kf/Upi-=s+3>sa +l_F8HlpS4#("!ThnpUR/^VW0IrP4%`A0)OKR;Gj/JACJq+/R1.DDsT-$>P#q,/$K7I#YnhWddNrDo"3Mo(]:QHceHZ$i5eYDF`2``-=F3^SIK0(!b;IC6uM@TF]C9 +[[Uk.SBk9#9l?e5ek#ldD:pQ:UHi:SFqAg@K.&6V]!UA1*H)HLO`HYM@Z6H%H%IW\j!rs9)WWWBH1nY^ +0=57so(:"g,ca:&Lfq4*p$SRQPNG%M7YcP.97e'\EE#P-C/*G +Z4Xo[NV[USMpfDu2s0Bu]Wc=m*1jRLK21&,:i>ZT!*f->LT"6$+qRE(%%\@;h7U,9ek7*Z+kkn"P2XqF +>1sUbYhKfOFQbQa"tNVA/WKqU*!on';0Cgi=JljS=-fYo(8(9bk:SbqPn'NSDT6?8-'R?i%4A,e]Cq_T +TsaXUQe&rF,&Su@7eRs1c^iu!J`c-SAD+9*\?Fe\?g\l03G?-rp5#)u?17UCX\-gd9))sJlu+&nF"Q2A:K.i[X=?`m?=R!Tf$BlJP+?aT]"4B2H&p)C"EtV +]^b?rl%NMND++'3"Ji79n9q_r<$dHJlQE+!^<:c=,.01@s3--IMSe_XfM42q=O!s4o4dO&>nB5># +%(&[,l^Gj6dX`HrVo^%+nJI7PG5<<-DO59^>kG0]0gq$BYfL_]-HC&m\M@J38@!#U6Q'i9oWZmlg#J'X +Bg1mNRL6_mI%)D',0*k`;h(kXC>WBT+ni;GrHlTMhsk4V]pfkEl0>p+#-oQ(TtoR&4'?Cq>P6mYfDfL? +l+%eX"s$(RM_4TSnIrJc7=dpdFp%fPNnKgX!`GSqUg^m'k +]eloGj/k07:T@ie?G#08.dN5<1*g#s@)`iTbDu7Qm<85>i2bWdZ:FI3U;'E'h*!rJ5a/TVq6mMV;>HN^ +>-G/efWRd5h6E\%?9N@JP4aLb,kPmE5VYU`M,fkV%*EES>`nj4L"HHR`/"Ej];=OJ_G.-uN3&^k+7D;B +G`Kq3NmTr +\\Dm'h0G'3csP?EpNZ$.e6h`03^%FRoIs84elpm9"OPZI6H>m +)^YH`Qm)-YoPfVmNY;3p9/jWtdoboB#o19oITA(.@T)L@5P/Rht +=W-d;:o`>Q0_tF8coCVg57TCFF84kTge[h0<8Inq1G:DB9AM:j,M/Ao_f$tCk)VM>Scqr)EM"o/fHGJ$ +GF4flm*+OaSfO@QKqc0:A]koIn(g:*g1WV\9VRO1djm^H8$KF<6pPg'Z'rUiKPt3is +G10'8FuuO:nLNElbI8Hkm'=X,DR8[]]45kNN]$%fV42dN??0C12q/2YA#1_5XPUF8JM"Jh8%XluAp9Tp +qUVq3"Pp*HF,c(Fd9/1+k5DR@AI5NiP5=^h?B&H*k39$L/KQ8CNjHC*gs#rPN; +P--RtW[#pGoc!-_XtgU!Ir4iZdK4>VU((Tp4?%D^Uj8(eGcHC@b)0bYa)$a5A2$2]Fn:#$`7;a&67uL/ +o:X]2Lt35Za/q;uAOjHpg\#nMQ=OB_(a&>pg#",JS,9spiaYPLO8oo2Z?UjLKDHZ/uQW6!aRru8^\+&QT +jIWnO_>U5AI7"IN3!*9g45Er"A*9fHJtjq]"3fipI) +0nRR(MnRr"?QNB%Dtg!#<].Kh)*Qt?-&VRL[WgAZ2Nu=6=mSP*Zs2lb^:nnio,\KL*&>XjKq>C1,A"J^ +#C_q;@ZR%2(O\mFcCGDRFi8PZ#$02\lOSC.QRB3\j3up9BJ371fr9@E0b*]Dh$0FW1>Dcp8^u\1$#)Op +[1_5PT6;R:el1?5Rl4tn\+-=iBsKgNJ[-Km_EOQ]IYV2ZW3pi>h8d!A`5lRkchJ8f>-^i%`e:oAs1UI, +4ufMgm1rMZ`.LMgm1qJCG1eJ7j-ihAj-j?#\CNU\fS-$nZM&L``tt?jo=X0!e38irYY +gj-8%mNM+TEle7g2rdo'2RRWTE7R4#"oMdV5c8MVcW0kbFX,]_NM +S&[4oX#.B39e*]u?#tG$>GTr.^q6=L@=JYrW_i-N0(:E/CTg8!3u203qA8#^cQ6]h5bf+QIJ;nEj]1$f +P.fOX-c#+"6Zg.*g,L$b\(![bgD.0/jg-dKh&i*Giic73^Q3cEi:"q$C%N+bFj^(ob)uUZI5kMmc6l>q +G_n6\f@p'0$>2b.KI/iOJI>\6L7A)JUoK\a2?r#_TZhD`+MW!*E.1lfp;jl'EmHhWW>,WoFJ-VjGj"\L +0@39ZPgXo._MAEJ]X\Dri.??W>*ATTon.2,gZj=B/D?$8.l\i1NV#R.C3$F07CtUHDYK0](\?q:WMO?( +ZI1*!g-ApVnFa\=3IUc'iO*[N<%Sj;;uD[R7d:/i9'RR2[M6k8-+`0Q2Y%KH9@h63/mfTh=\)[RW:_R^ +65>j.I^SpCnB5>%-+$=I]gQdBBaoLC_)$8HiPeZjLkc=,%\Bql8kPqf4`;71bla0q1fq9/^Kbs +*8>7o74Z=;G@A,43\5tCCa+kB22`^K261*qY#=YF;fYW$O"\XL=>>)B26lllZM*H"mF?]fb%5N&fWf=\ +)>H;_d^uFN>2j,HeFL!5MWQlWQ.Od=Z*UMJB)?a$2"4L/IYZH2^G?@aLS#j:!_06AB +.Bcn_-=:8Q+ie^fpI/)*-q`;*m6Ha*W60U);I5\jiXN84.Bg&O.HOQY/%k^,Y>sKM*LH=H^X_D7O=TCZ +rHB]orEct6FGi_9ebVidYL6T$j]1/!oLPQ;8i\W&*5@`&f.&kB@o`HRU`@mN*7kdYA%Pd,3jh2oTLuno +*&NnEP=$b[2uiB,cc$r(arQt9o1P>=3i,'\7<(nEeI#l.>d`mkPh42<'W%@@Cf4T/iem]3%<p`G>8j +B>15?mf0b&0Pn4W32TBV9IY?sab[V6i%i`f\lF5-ZA4CkWBHT"<^S48DN!=#?c[=,Z*U^%N7]RCQ]]j; +CTi`M>CZTjlnZH3PS(>l)<#dE7bEXYYBYfB=T*F]C$"29[7jlWMhd%a!uNA +&O_.R\CJeVP.OR*'tORq1ilt.ah$/EGRDY3nlD-Bhd!dEVF5E +];%B^J0T"NC%_2eJCc%k9qFbq8<]BRn.j0'gPEaQ7dg7S7QdP20I#GXQ)q+FiE5nPrtddN%#`-^nnsr' +B_Hq"l\=jtb(jPHc1He!drX0b6<6%'Ml\ba)hrPtPC0Y7ROGn-[l4u2W'&FEW`pN$hN%pGEQf#Es,O"l +$7Tl%omJ)SH89e@]iCY6_YE`)[mkZ.X\j#M25Kt&hd_>jf;kF5A[XdM7OM7'H[bdj@\uRq^m2ir0*3KG +d3_1aN@t_fg8Bc\2Qi/6Z(L_/j7"O(deEH.AZ2h=jA5!?6_=%$Te1%laAZ`C7:ojOGRK:9bC%-FaJ3Tj +h@5Mt2t&D]e_Te!Zk&-q^LXL$[gO\MX.Z,3FOQQj0='o*o1E9WG3FUM<;ChbHmMM\,JVadb=*HWDa%Oq+RaITR'mWCT=aZqmU9U!:/^7Yt"Kof=r/MYnjA!#234%7W21KN\rqFF!:uUr[M&a2' +8]2L6;9H.%;AD!\dqGJ6?KKCqi]1qQpH5;BR8(i]Au@(7?68XeU/_Gd12"jCO'N]NrsQ/``,.!S?G5o8 +?eXt5n%gjfZQnpOn^iD3NZYWX$fC$AhgKa]&Wst4'sFC^8W.CsT1R'ci`&:-el8.LTt@122Q#0+-'74? +NqYNLbYK5dIXfD"LYq/lrs;iRm4FO3]k%i&\'3fTh#>/Ak4Rj-Jq6bi+ +=4^4Bc0e`[drt/M=jGKtNm91g,0p9:AsP6&frpTl#?@ss%3lAd4_!gcqs-82p\:*VCAXXkfb"(8B/?c7 +AW!-fb]:.9=qBniF+R_&QF"9(EKF`l'?(6.R@1s"MK3C^Z^ghkAi[1fb]7GJEjr5u.o+')9?KUVpb]-j!Et)_!E."70J;c39c)ch1VJ!N^RaP7l6g>9H +bB"6_q880F3@WulA2tLC4NlD41*:@7f9ta50RD&c[eE]1/j'MA6gF%"&(=)9Dl/7eV@mEl=jD3ea`JO81aB>s +mJRib;56c/%j@^DOb8l;e0l&tjc!OVB(O_,+bpT6di2P$\UpKgG\3j$8*r^tM9+SL$_W"$$];42dMg4D!(jormQkl +F_^EiL?W[J2m]#uOn<1lgC,I$LP+`s/8+O_B0"`"\V$=3CbOh9hX4.*c7EUT6cXF#M5K3!bAUZi*K]/+ +,jhIo"RRg5,S?i;=jE6VAiWfPR%:a.TV/c\6F*$P832!]1[*Y_j\1ZM/E^6PG^`c+erZ?Ep[1(CfR42% +]#V"!P2d%,`,FeVFeB'uJ='nXHF48q,[j[E#p;a>]>l&E^kSL4ZF/F8rUajZh>:hKmG2R=noVSp:UINj +"Wm=3i0T[iC2\YEkt4s(J/!4i_hEcMpEQu'1?EU4a/qVDm44$^K"H^^D(l/d.IYK4S +_+^/jeYlj4a\J0R3K:QefmC5_XDX/Rk7?\G%HTrWrfT>[dY0CgHS+k4oVcb((VPMqNHnd;7^:cj(2KsV +kjcT]8ZW_DG^m>QIRUn5-R9\G=HgWjXdG)'"hQK5?gl;WOThdSAIFS+79X2"p=*'9;O&B@ON*Tg)6XuLUUI^a\eq1itV`#^Fh/W;Z4dZ0[OKmlk,b,.QN>=Htj +I$CHbMqKTBKCRBh?RFsS*n`$,h_DlGBT5?`.S\ +ke'@T4+6qGS^?(pLZlRQ5PFUsm2WJ.nnY"d<^&q3=!o6gd(JIkkf^0sWOIsPnW$!&nFuD(IJLr6kem!p +^np2`@^"T0k$uj7o>RPYqk(sKW)r5ZJ&M8EaMmB2bIX4CP]]5uHdf-3[]O5ZYlQYO$R"']^ktHo=F=lGI'ZL0)3sPQJ84;AhfK-WQc8iBT"r'g-?YT +p:)i#E[@Hnh=J2imHr-`mT:KtfBju\dj;*S0&(V@"FYN$GM?Q&=H?XeS9?^^[BAS*-JG3'OjS=@pL%;d1.XIt]$]F'H/7O.cg,J$jaB*o3qKqFbL8VX)qcg6H/23,^Nq'\2)m4)$$ND! +$(4_`P3a13l__lT]BHP@37`,8/m145Q@$WTRTnOjMguR>*e`jGYJ2?KZJORUlPZm.q&,fLa'SeLLo(#p +IJX8S'\c:KLnt)Am)8TZ(H+M9<\1)P'G1AP13UT6bg+juV3no6`DV41dK$@N$@\sV$JLJA$GNNB$@8LM +$Mk^HP\YZ**7taG7k=hYLfd7Wm/9g5`T1l+/7l';LntOR$aCD=4'L-Mr.q3-Q_GJRNEAecl-;S+`DUHD +CP39m3I%BVSXf5a@it.]*YGt3@_1p##dD?I%'RUjKq5V9a?84#%XB@]H.Y^LK1AkYi1SVClBg`##>ZO6 +BjjYl_Q:@T]@#$@CA74CO-V1nr0DoS$npAAs+2J]dd5/7V&Tm2I(Af3K5#"G5I+.qo6/;l8CH2:nA@oYs%,J/B-tuX]S1>O"6N*44C<68n,sZ/V1Zc +HRraq8#b;TZ5$"e4(q,8`R^$N=NY08&5*%]=GeeA.;!"*`DSDdLnuZfR8Q.Z+K7_%Ak+Bu;*udu@f,Sq +=GhA1[pgf7N88C_XH:itT)Yop8g+EgQ6KX1oNHmBVVaI[pcu*K9J/U^,s=5&^N%aYW@1MMe=BN[Z$*!X +fYDD5&OM^+Q82R>=N[;,.[Dh<`JC?aQ?LR/P+6jB^dcA3c+7G3^Ic)FK-Do7U.aK!>JKEs=A$$*.$c'Q +pkX4_[UL]JJ_l9\,Y=';UP@_AZ&$Y,$MiFd.>VL#LnuZ*L96@d`\4,PGY><+5u)5b'L+]"pW+C$mA?/E +nKq"',enpG8[4LOI?$Bg(3LR6HJ!cmcDXW5[UL]"/mS%WG0-SBoMds\Z_+Le"\LJ7Osh>o1W8-$2-l5@ +jBLK$@dgmt^1Jfp)d>b?Y;K7$JS4i;09%?:g,4o\gC:qaPJ1r(jmr0H&Uim1.a=#](4N+Um0;C]MA-!S +;'>;[EW2T*_(RZDhK@auTO4e_75a456a1 +fpNn89;6>mKf6WILk'?TU9+>c:E51Is1=c_"TQ>JqiW*NOjqPn,$HB/t_;b<4RiA%t0V&F(.b."o? +U/aW3dAeAodA$qpTs\m/)o)B/p_[VLnRQa:Aer,GHURA[4&gPK4)A]f>7eCWS8#`XZZ>Z,(f!ks2S!!M +AurK8nsf$i1X5+N?K<@J8TjEXckXg0:>g#%DjO/R6,+\>J"(mYS;5s@3d1p6h/o"G9ch4>%H)Uu*Klb6 +hp0_)Y(o!I^LB.=]!*J:9=`bm[2Z_%I+@;&I]u>NVJZ!mLh"%iZW>+!3nX9f23]hZ85 +)<)(1[[lgUQ>kTI^>o2[p4D-i472G3XX)KJI1n]Hd04pGM97t^HNW*fA>c1MX[SFu6T;\+FdR'mT[bsM +Y0CtOS7@>fYO^UiSkeb0B/*FR*&20pQejH,!FGfG +7\>*=`_,U"AF3&$!`sN*QBG/`SHaSt)IJ6/W[T8SKtd`IB>,InDR!8P6f9KNOT8^]hCae9[^Eb)b(\(h +OiL'dMj8uNrpa241&pqdm'2_#5,aYfs.3eP3-V`;p`?D8lPk3LX$o6+`>8Eb'X;:WYl6_ucdVX8?e1r@ +\TgF^l_6gjd5c-Cn(19R^H8E`f6p/jFbXd"<&uj3S[)FDP5q]3Z3/&O +(ACL^/OA[E;S+k&#A(+q2LK4H;ESh,BU:qV1T=a(?`/(TB&K`OdA-9`hsqVDen^5O:udECPq-r"Qfa3X +(Oc8S13EE_e'%EM1HPd>Nm4.I:Mb=p-^_;g^mX`[Gm$hsP'B<_o+s.Bms8!J=>7"s#j +7SVHnefE#jMGc*Bg-S3"Mq=e2a`b.,UPSE".()/o3`#'J0qO;X%QEY>=h[X#WAAaOMl"dtLf+U08hE]A +Ol#_Vo=QrVYB]]om/b5D?/)`a-PW>6dR>*s/lCl=1>BIrD,Yb=3.oa@Hd$;/4.(/PYW8G^A/Xe1LImi5Fh"ctLPhP5j;1tU +Lf2u"ZkT@F5T+a*Kj +R;!pr,7_IgP^4/m'r;,"'W%+-<0Z,!H7DNMa[83Q=qRSH0-a(Pa\dl6:Q\D;/'9 +Bk?*l)PW0fC-07Cr3e^c^)3^'R:X>^P`Sg5WEG]fl>;Zn`@*UY'.M-!rcXF5ejYqA +?ReZ2-kV85%n\s3og4Nu%r-X&K>4n12@"XJFd(e&Qg0=M.Sfnal=ECi)L5`cak6m3h460^;/4HoHBd,- +]>f3:.6\WGG#[0as4P(k8=@al%R]b5,4mljr)N$jaYt3+:sdri48%UGj?BS2iSk8srERS&+erLJsdqJ6*YP)%Fs2#B(W5$)?hH5JrY&X%K'.'l#qFomGF/:50AQc"W!./SBU0.%O"3k! +,l+0.'@8PCL$4G0=)#@L#l;\ES=jWH'>r.RQklB.'7J46W_P-Jr?bH^8Y]@OC\s.\`(co6[\]%&a^\E) +cLS6CX41a1ae+nZ2P$Mp**qN;Z#2C7e'X*f<1A%T:/Ge2R(*IPp7*pV!k$^K\d:2lrnu*QJN1)XPr?'M +G`O:qe\#TUFb36^1RCB$$*(udlNEJ,:/EgV22aTWf(-=!5'7MeX<.1f0nQnA[)b]ZmpY%m9q[oTI-ik( +F;&?![(&(X:/G6pk@oq"SW$_*FjYI]tm%G,odsh4l*i@rat'W0=rF +-uRr]9=EjDnX]R.A*V%loO%64e]i8Z_sjP;KpO@4/h93BV%(fU?\PC78L)bNl+3,pGd&Jt@e?*VHPQ:D +=2R"sVL@j7hVYjc2[gYf8\7D$0g?N=1?f%Eg&i^`iQuJ#.+G%7N6(s*N[5Xk)tWo`qnXZioRg$'Ua7to +=ONo6;JadX!-P3_N7/]nc&"B[647TTb[J#?aa'.W/Gf:!'7SZO6),/qEioXCM +rJP+h8XuQScdE+`\*)N-nQg-dD`hklf"Y]_4/Br,(FD)Rknk&2'7AMV^a!*lB2=*<"CIFsoFlK8[oi9$ +r?mU=I+NcD-$PQTo&^B4Dr/;/k5BYIjY-7*rcrqh#;7d#9\4N?))tr-2G_PNGEh\nfn8dSYj'$iT#tKq +YgQHapN7NfHQ==)it9a=a^=<:B!`L10]T3[JU,9A]YEtrkd57Cll)>qc&H_8M=T">HA%V0.jB)!U1O>i5QrfqrK^f,Mi>+(!gN_Uq^&2&W)sg"U@5`C-K\/GQ +^eO8d;tRJ[Y/!_[\J#jB(E.ZMXq$F#/Y+:G7 +5b@TLZgG?)?=4i8EP0'qrWllGAO':B.da%d60=)q2VZbFQ$0Sf8ulJW"/-7t<)-X..Qs''YXdiT,]Z\W +A+NYpgQb`a.]7PHX*Z=/V4K+e*?fRSBO9LnajJ$7ba(Iko`F`Hmc.N=d!XXo"OMRAJU*E6H?Rft"_R:F +ik:$'W(H8Mj+D`Md5-&BTQ^j:R>kd(2muVm7:C/m,Rl]dRA+*p^Fb[:9Alm]Af3as`9sU8D0d[EZ1$%< +amZa;E`S0;It +Vp\=\*^ifc2#gU!:F19iYKRc&7%R04lCLUpZ.jN,JE"gufK>FZF:'aDKkl(l)lq9D=/mEi.Odm[<)VlN +Y%e=Yo_)1A.J&PLd/&$Ml +Gi,n-(5Je#Vlm07^]PQ.!lkT5T#5=H`'+7RNu)%?WVsV6q]ih)iHX<=rt\tUehfBWd/(W-q?LZbqKQLI +=s%ZaL=SS\ipBqLT^I.)TQ4aph!#TN=p&jcft=]k_:>qWc\kWc$Oo<`,2@IlUq5-t3LS7jq@9n3ksKHm +J'bd6^.'p7CCP,8r@Q1Y>5t7EBmmW1.BS*tiRtV&O_]ARB`7PGjkB*pH>.fQ#.6XohfMbnKpF+"lW%+k +GER^JdeYrt,H];`37Rdait5I%3;`Z)KecnY;J`trf6=%`eVhXUo3,7>hLB8<1V.ap%XrO9k5t7s];Fc[&mnL$*Fom4t8=+ni5m=nYnY$_k#X +phD7Z35(S\\H_&q<67=!VdT/e_na&l6,^$g,MH,RI=,?hA9(kD:Fa?!1a!4,J02\DOY9hhJr4ICr_r^,_@r[:MA-Ci$Yn3ei:C2B_3,`3]U2',MQP$ +N7,Z[/b-g&,TUES1o +lpf&hY0*!tKVbqp_G-HL%aP/.=iZJ/U88X1cPE^jDU,1eBAN2X+?$eZq08HQ;8;>/bB_h`7D,?6/^pgh +b.';;:.%U.'^7JDCLp3S^'P1LXS61tZPBUmC0^R0m?[ItWN$m2?$>dCiJFXan]V9WZ!A9F/FCg^/l1Ne +Rtc'3`#-*U]Ztin%lnCDY*'Y/(]drU?#4frZI;PdEB6fP +%66OWB>+01)%A2q56JsjY!JQ;JO>@FViOa.iZH*@k7Z\,";b*'Vo1HRZ"2?a[(?ImebWP&C:W_JHNVi& +@Q^,q3$VUp10,7hL0W?t.+U7b^0$.tMC6ehn0G^tSj\XXFgXE@*(EjOK4'@]"&r#7qR:g=dKSTO%. +q3i,jef2).4p5kFeCI%[qop2gc+29B)MV9Z[c=Ue)H?@R/9CDn6K3iEnFBn:@9_hb;lB`k>N$$M1 +Q@LXoc(iB:p/ioicd'%M(]+!EF&5`6\].j=g&o?_0mMXhJ$$$LR\R2.9<-_fit:)h3-7FWSa6GkmDAYc +_OM-.EqT/c0:gGslY?@V28sjK9.(j>m%rt'5M&WcP!/[15+$+TGQ2p5n!A&u>ag/V@=S<#8l&WMq:)1T +(JW\#E8u88P-n4qUb^8[4h(hY>3P3bcecEdZktGWhr),-Mm?!F)YiU8r#H9:g9L0s +T9Ms3Ma"PonN>E&'[k:S%-caP<,\8;GJtH$<*BDPbSojW=s705?aH_Yj1_BQ&8c1?CHPTteW$amC/;qp +G+6'%p=$+aY'%NrlE4-;2RST;j1k:ZI5$,L(L&88FXWff0$L3\Ms\rimYg*aS!l-*S,/^`8A[Wqr8kg> +Y<1SYPV%JG#i0jJ(CHXTq[KBg-XbHNj]8jD7:`?&^N@d1gXWG,?d8-T>U\H[b?UGJho*IUKU34G5P=T@ +7n_![HIVTX@AWDBbD2(lSK(kKIOQq=g?m>go0X5a*aSCa`I2Y*:CT$c4rhQINBX%eFk9tajHoZ4i;iW; +D8R:5lG=<5.96tmHjD5H?9Y`dZDNs!1V^Ns@V?]\Rc-hcpLA/CeQ^%%PLP)sG]]TfI-;Z4O?DKu]1;!gO( +:h#GYZ+:TgB%&gH+hIsB`K?`d!F3g'rt7GlFurb\IC38hUj?PrnG[TBQJCM1G0sFta,fjZVkNq89F=+8C[SNLk=1^AX[a!NfpYm^Y[A!Q6c=Zn9-:]'ZT]4:VN +G@p_(^H.F)o,[q+^T:Z-nQ6RBY?2[O`7$KB%:OY*QoTMue&V%C8)YoPAGrI&"ib22[+JG/kf-u`9=7j5 +@rQhhFWV2P +ht"+ri3L5kdbl:=iD&AUSX1*F\,='`h.Nl(WK3HK`fm3-o@.gkT!8^%Mk_id,>*a$O*O=G;"?.UaPQ(( +lB&F<=]YiNcP!;0hb&?3PeQ,NXrk#SI)k<4IDY2grpUt$VWUn;-a\LuNRJAC](=n&XEi/=o60HE5/`H> +LYef,/oW8Uho[f[eGT36'Zhm$O4,"1uBmG0pS4rUU9_CaT.)4M#/9 +%?7UK\=Hd5lFW(bH\[*edJhG]r4^2EpHLI`LS(doO]EkF'_C +dgV08ZO`!1C98K"4\4'3MHLbIHaon.Zkq`KdVT6"*omd%TbW[n&Z(,T;_AHuk*[%D,M^o*WAdjuFOjU@ +\:T)Y`sSloC>SB@B?sm%OQc?\lG!nmAd.2HC6Tc4*P^r+>jH8GT$6Nni>f]sQ^`JlrLl*+O\t*AIg*To +i%MFh54-glpfU[f;g^8pKHl:7D7,C9k#'[pQSWr8;$M==jP`BX%ak!t?N$d\^_Sf2*`":^Xo:G`Ca]CZ +Q\B](KDe,c_N4t6h/ptMmeX&N2LUhr?W$5[,?5-C'/J-l)//?k&?opNA9Ig%LRl*SpA2P^H03cN8Ie50 +:*\AYG:IfVda4AsB,:6eYa`RR,C# +RpoHWQ8*NiBK00X(2gfiGfQn(nR0_o>9n)V1K[&Zrdp'4ALq5s1egiO[r&\[]G0)9VQCik4bett]B_Lp +8s>hD_"5e!GLV,[6+`lIbQD5Fdr05R0E2f3g.-]%n)hRr3dCr^m#*n^2VKW,BNCNa;1njTDtEK>2qD;? +<5olR`nST3gW97TP,lQho5T9/Z#^B?^Z2AU[B`SSF0]h0##E$8atf^<\%`(/]PT"np<-)n=mXT0Dp=u8 +4k:XMRa]DXhcZuso-@`&(-d"]H_)6kqq]E!$kb?V2YR53!M?l;md*:b]p%=Vi"cOn)tjM+j/%Hq9AWF! +K2P+GX^+EV@?'Kb"R[Bp;@FUsc)KENVheUl#JH2sd3nfcPC[rj"b']'YP&M[@hHq9@nPSoSJ_ +pN1,s%7_5J(Y?gG[o:*T.s\a>N]l92IrIo?EOOctGKk[u[WIcMXV*)XDFdC#Y><^54dc7toCnSX=iCXN +ZVJ_""6O%Eq2n63QRp,cm&D3]7EqbHXtW*-'JUFs5R]Xub^5stUZ%dSG*b*/,R +Q@)iEFn;Zl;p!$-Nm?:iDAO>-hrr!ElDn26hEn93f:GnH.g@FX;i'OAg"j`N]5X^ +[&bb7/AcWh*U@AM,_s+#pUjEo.b;;WdG&m@j:W3\rEWdf6h3gPZ>#=`RE,#?8uFb +@-?XBlWPObd>ho2HR4tU^3T."!jUt@\Thie[!qCIK, +nJCRt*]W@b33uCso`'B0&*fb^[&)K&g/@;U;.0?HI+qQsMq_-Gd;>kkT!f@!^Z3M'3iD3g?^?gPmN#u- +FbEt573Ts&ca7\6T.i)%E[^M-`W;Y;RCW+SA3:XpcE-tEQ_e0HKHA6m6%U +@J0uX7GQGZRPLip49E%m\8s<u'EEP,\[0oF*i'c9=Y;&dEhoJ@Z\.=Q*F()eFo-SP&bfES0h'h?,Pfc:F0!%^=:A9f9"PNIU*aDnbpEJj%da-rB&C8]\bo3/X@7\a +@#a1$gQe:8-iR%4Y>_H&!jR[XhF +Jn'HMhGLHGY/2-.bq`MG'ZSmk#ES6$=ID+d!lYG!7C`J7'Q4e3:jiM42dc%/0`mu0X`r:_n_KK:ShN&#H`gEW#6i$JdO#BUIkHK]U44hghji*sKX7OnHE-V*ndtT#8 +:Pm-V'-f[80('ZI97qGql9!bX;*;OZIUd7SPl8U,U9>ZO\MQoqj^5S>\7oc.@r;@=XN.2`Nc`T4Q$sA) +_Y5hUbC&-a4)c,jl!96`FN82!&(M3ISOu:rYH-14Xt0$#h9E.!#7\#Sfsr5&,nTb++.sNAOEg6ciWu!f +9ka+>pB;uZrq[aJVWOOr`_AXDZ<*"D+suNMrUJ(V?]KS6-D+QVDq#f?@5BlJUV6NMRfWqBC;\aLhFFIt +Rb3+BdohC>U]*@#(WP6HMe1SA[1l360f'TMWLUH_-hfKV#L.%E)&;bkEH)4.ER$Wn1/sdM(aE6I$VOIt +PWUXJa8BN3]`Wn&RA*Q2ntmgAaH68anMH8u,a4P`b)>ZBe?F/]B\nuR3-,gQ'QBdJPoQfrFr>:<#'lEbe9BNp;P^^V0Wr$AY!e8FH,YHN-4VCgWa +r>cpsmF8HjQ2]W%kRd+kIOFZ'JU7"QU@4H.k>RUQr4E/DEai`oPSJ:D*be<^W\V_F-ke?(M_^df;2]\$ +qT*ila8>AV%]c'^)N5ABnh'7o>c>J9.Z/./D1B#FMC4^1Y'M5Z06+PJ[L_-slKncr$98\t.^U%5rHQcb +61H3RAM/Q49*q2km!RM%#mDF*r?]":1]%Xr,62V?CGt`W?dWafZ#W9mF7Ls@m-hUHbNgWPP],c\*OZ&_ +4iLKb1SGj9l#1QtefVQ)X0lge#tb +Zq_(%V2())oHWWNSV&?aZ%3k@'`*]9)#h6(B@?*aIjN^i1L;1]S!\-56A?GS=.*COVt?bn;pg99E;IdC-T5%"1%S1OCLT^9^Jjl"dpS=!XL=)aXT +lrO[WrC9&HfXCVQUtK@-$-m8n8=HL+]MBB4Mq&RjqQZ6/t/1V.t!C,`SG[f>3fi%BVKo7$(. +KX>(u0"ahc>l,8Dl["OtV+"#A9@J7VFc"2kV:qO,;Q\8fWRduu@/Y<9lV_To]#:1[?)mk6/oaRBI?&Y[ +,&NhtlaSs@PRNfFFfC8M913g./oeUQ?+T4fT0$o?rl/ZQp3*10i4o9OmGq-N?.qE='.kQ\/3Ajd>Bl\) +IRH6%K,4I\+$'^^^Drj"Op1]32tGq&"i]Q/`gG;c^GXYnp%[*JN3etRD)BEqq>"O7K_;`E(sVKKqgOg^ +6gb?>ohQ*225V5R"Q7ZAZWc&anbIl!YX^@&DpNK-@(C8?aXuPc"_ma:Aa)Eb!@]>4iefOZ^Jt?[dqJWjZ;G7R_)n)*)RtB +FmI_`H"f?tl27h66[MrXm#::YrPrT+pSlnE3_teWnKqqi7T',iVrJ"Y]:Jh;IJ$%bED"WR?4Tu5^H`Xj +)3%6Cdap-ZqFG_l]I?NRl?6s9.+mo,`H/c=l>q:A;L0>!cbLVadqH4S-Al#O@GVVB[.1=PWZ(J2RP8<->T?Hb?# +PdY(n94gr_[9bW;]6N;UbSa#qR1[jU$:AG#9?I[tFd_2i.5U<&V1SYgRGhgYMNLeK8-bJ!;Md.r$;tIW +o49`1m9iQ-N%d6`oW^IO^-9=+`S3'$LN@pRA1:)=0@4)i7aP>'-:qPJC?]L-4?.[Z.X?VD9]TB7QlLuj +P'blbo/=?Uc=`1d($r-I$qI'jN)[Op*MQh98REbIdA$qp6#kY0N?c6n.)%u+_r$K&V.0CIXST+97fg:s +MI%kE];dZ_MV)-@rHG@>=,Z@=>#ZStmCoU$Km+Mb4HIpa:R6@f\Dnp>K.HG,fq-YtHK(!,KFf%;P)`Kf +PL*7[Y3Idfg4lPUc(^gd@6I$C3Ng/@J_1J-DCk:`SSadI]#r;f3"k*TgK@e[ZCBCGG+Ckme\aPJ^Z\P( +;hjQjd-32QUJd&XgK?hiTkE-^+Y%WX72?'==mD`"c\NT$edSO$3Gj%7jd^7pmngb5dCVaB<9nO2Y)B/o +'LPeB[8Ebk8!K#QG!2+MX]f"'+$'+-MNFZCm22,1>U$H@20=;E8 +)9ke^ef44*38ZT`!^;u%cKdP]6!.XOspgC'DUOL92e\^;#P>)F#0eo2mu4\ZD=Gb;BG`@D_J7tkA;!!Mq11?C!@&*\fkU2RWa6_g>:rm +DFr&E4".A6N8oX$dJ,"J+1"+8J#)%n6)i?oB8*Af^C9E@n[CgKah+MgVD[L\^n0O$hiQMe/,>W#G*gAG\`t,Tm=Nq= +"a3>,f!,_Jk0CbR!hF#]b//#jMK*^BKk6(@KPhUufOu\Y*Tg"AnhF^mU_SQmQ(N\7;fh +N5"A%P:Sj.a(N_A[m2hM#'onM48o*QGFY'UpGj=W4hGZ%\Lk5JN4ii!\jk^Np&$ncCaoCFgJ\#?\"t(V +B(kEFES+/>V/*ct)`Mt)>]1Bud:5U^"9W.66e6&VaVl5O3k8-#=W#5&Y%-8W`%T5:[H"r^Yt6aXV4qa"i@/!MqV3J.;2Zu%N'MXZ=oQk#6AtTLIeKsggjS]6;)\Zt?$#C%*D"Fd1V*FM +L@RIqSJDPhr2YQmp)XAE%M?]or0JD&^GiNO^.Kl#O.:e\I6hjGQ+gPMr<2h:[d4"/s2M8*Z'#26:U6Zf +??k_-Pr$22RBtUdkDCu8Z]"%Q-4M,H]T?!=]*HSam/WZH;Jd,kG8D*MiCohi:"2e"\$TNr[)aQb+[K0J +DM(0XbE_l$47;_rgUE)'-NuXP7%M#W%P(IflB59f,Se+$@CBaE28f!Y7ZR,?jqQiaeW=";W5+R!IXu$4;3t4)J6h +XXIdr^GKkj>sDTX"8:uh=,Fpgo +E&tWCm2i/bNdGU#O;#.O8>`?QMi,hfMXf5e[fV=G0VYM +A;I[(V$/UeIFKqY%Ft=FjDXljYn]`hi>$'k4iHLCD9NHQL_B0AO",'fO1Rf7.W;H12dVb4@I)UhgG>8" +>rRB_^$NccXtUP3eMd,';[G`Uj!WMbJDW*!M*'F#HV3p-2,D/Ggi#YcApFbq%2cY +K_#Xklh$;U+Hp+PkqiV#L\.Jt@ee%'MXrLo7BY"(b\rC3U"0[&beUp13T)HnYK32d-0TAr^kbF&[sSaq +-%'n-#'-4(caNckO28>r_"9@)>/CA?N]r=9oJ4lr\'2#r,HC!)B!RJ_\,dt[+fup:nW3?t(!)VpONRa_HspPF2K(`LrX/r7o_^At9JmB*cD4#>9Brg8,'NLX +>ne0oBj_VmP?&XCCoNWH71il$McT\EA9gmaD!H?CE=:BNfcTc^>8FYfONT]*fYtc^+k6G''8L8fK3LM0 +m#R7Bl>OaUNQ,0_;LZjS0NGm'WPgn":;McSh<0/o#0e.A5(]DZ#JK)co!qt`RA&3%&u)+4MrtpO;C-nn +UH-chXOB5?,5"TC[!456C#c8R$2$j1.IJ%\]Ao4cd`LD4es=$bUYd0M,O.,SDeM+i``kH$s/"ojmhM,_ +$I^d%?d^^!Z6%gWS%+.1p=1/!WBW(h:"SF*s8XN>i8-.:V4V$/[H=X\+K8u\'4JE=_?r];t-[QKApd:9h+bgohY!Q +ATOpeRaTM(;@.](_-X;5*;Kj[07PmFY`\S7i%KLYp6Bs"of_co:@E:"VmV`fqBaH\c[33XcrXkVN+@th +"iZ2-5:aG"CV2UiTWa5FlB,$7VCs@320N(_5Cl0XXr.*>LF(lGT#S1;cPj1;gAH+M@Xl3]4=OEla4A/V +=VGEf@0s"[Kf].NAVMM8A1tM?@,^!!/=hJ>iL"m6[fhB1GY$#%*.#n[s,PnJ=P^B(Vm"hI*d_2iV>&QG +A1L,sl+Jr'9jI.hF^_'+Un+a6X2[+AZXhlJ5A;"gHJGb8b_ttX?huLrqh&m8JZ$fQ[WXbLQ7RQ9Qk:n3 +ZWKJF;M=t_LMO"Y:Z617Il9o'*9jhmfJ-PihO3T4Q@5=Z4-a2$c:!^tEY$0mn9Utol\Jm'6nOgI.RnlK2a]6XFeei,`:>3ie`RsDU.8D,Bm__[-VNj*4U +UJ/PafjU/64gYIiJipBu<]_9In%?,IpL22<>.OK!]4bk$*\%$0bhMmQ+3K]4];:s=(9o3`1uffTWp>QY_"RHZAhOlhP+ir(r)Nn0u,Y3p=!tV)D3@rdMQR+/^XOs34%`3d)qQDs@1Z +>q-'0ahjp.L/`i@GTWnuIb?_d.`,g;EmHkZB=IL:&+CL8Fh#,SlmnX=G=b6@FgtC-PcIHr5a%"bcZm&g(c)Mupmb]_ +2/rL(h=_6C,L#eVs2($94Q?0\]Z`XQ0S0Z@2._O^5b4JiGWZD\jd+WC_`_agB\nnLr?+<&MOF)!"8?SC +=)O8EaS]GEn[goYbKYIO[dJ4u8ql1/ZtPd1Nq!q2l8oLPl1oOn["9@jJMh-X@C6'B.)iu]p#QWao&.^h +=TsM,HrX>7:eD4hRh_QLImWC\AKV4D39H['.?g:s!Sq]GBWZ#l_\u>R.7"^kM/, +Uh'4<%_c$<*`#X*VB(U/>jG7Q:1$8E()bEiXoFR149[3o]S=Xa7OA#aej8Qm!`/Y!$ubQb?;.]Jn/^9L +c%.e=-XCs+]LdH,4-d5EWmpt9HYuMpQ0`@9Lk[/8Z6=KfEJB5nCLtmP +%c+j_6<-fD9n(q.^[:[6B$CNM;jPm>[S-FP*^[IX)OF`JUFZ5KdoeI>>cl#93i3nB9.H9 +qL)$#H2H^"5tk<[K`8W[OaIk]hi?Yna$,(#^Z0S<=!aXAYl`F5&c]-^3F>Rn;Cm` +;`L.qs)t%F^M69UapZ+c50mGJ>+s4Nfq6(lq4*kl`a\HC\]T)[/B]a][T\66hSPhT=8js4H@,JE<12^j^RFA1 +:lc7K>J7enUKn,MA%Ye\q1MthTS$:i]',\-rISO!ZLR!oO.s&l?Rj:()&Nr5MB4,%DL*hRp+[\mZN/r2 +0`7&\]BrYj[)g'gHMC,KgghmK/^:\"]/)X/B`%pc\`Ns*IM<-jfKek."S."]U? +UQ*pY$D`Jt:iS24=c?r`efJ`"5Sgh<3. +j5R/qmYEfnPTkhOhL'LCe,Sd_'T)X[F`DPf/kj2r8?q-J$Y,BtA6%Xb;kTB2hnDDVc3S?-g?&itNBY#; +D>AN71%(G\b%4]EM#>Ra4Opll<mA+ +k2p7Bof!@4^):DPNoPEbhE*o)IrCr@=u,6>9TBQjZolso8=L.c:VYSY/>h[;-c`sc)'^p(QM%>`h>#Xl +`]u14RWGi/CMqoQ_:kj[Q4i/C\Af^\+'T87=AR%t6@UW>Ol@l/CmG_t6KGgR8T5\`RHu5#V(M>:Hgq9i?(RlK*\fG(@#6)@,S55Xm57L7!QT7=="k7pS$SB48 +^1_2qjsL0roFOCY7P!O=c,;d$ZHU.ue;/f"i^IAj@Io@L)R;XKGN8U>i6>RBc:;A[:*0.I.(Rs`631C* +9f%]61p07SAg35B3/2(:UWMS/'6C.ZhOX0`j9e#s_7>@BII]*gEhjKoW.,9uXChno1o55h[kq#mj3'E? +"!-2*h3(urL1J&;`[RsTMT66"TbWFUnKstM1I0:Wd`c?KJg]_hVLtc?+YY+>]5*q!nD;ZcgXlbT_"9fU +CFmKno=Cg0db.tW1fB?Rd8N*3JM'q8,h&[H0):ZA2=\+@:>?L+>gcJEN.qUs]J,)'XFnbR!(r"2T'Wjj +l6&\]A:sPVg1"-CF^D3*7chM]G08K))e>)%j1UG8[#g"op(4$X0V"Hd^mc*4jdTiWo]`7]OP'!/05LgB +e3ch%kn6t)'W0Vh9.(_5Vi_K9qtkKHaA*X9/)dhsI<)-b^)*r"YH4Uk4PCf3\m1 +7J;E6gcE^4r%1Yc8Jc-/7?J^!,#-+")p;'UPs+GmEn@X$3K8*6SOk2o&Tk^\D"2jo.phL;nAeGaI#o29^?eoUbCe)F**ruH$V;fAmr +n]b#:(mBG8MReNi5&)mL@)'Y_t_mo`K1MAP`-c*"O;o`e"PF+?35R7T%7ahM_nrl +k?GJAG=,bbZj(H^^:G8i)K;`bcXLBmI@Bk9hMYp[9;'N:&]-=I3*X-SN`jK]Mgap0Zdnfl0+k$%_)#0* +^I%WF*Ko:%`%UbkM%4b@h[:pMCLHU:guB*/FO>[jXNDEjRd(Kul'm%uYr<,4=PN``p$.o>Da+'P.rV8Q +T[gf"%A&Ac*ER$M0+J"E7O=&%Ytp2l.ahcD:Vsh2:kI&f[prB4e1\X$`S[`h@dh9;D9`gXHr/\ll2;>0 +]s$"p&._Ms')DU_!I@?9 +'m`#Y!=:&UFTk(GA8/4)E[/Dc$Lf"p%U6,7(NBDW%K97%gIhW;17<-)A_76=D$Hf8JV/Q)1tm1$9Kn +KZt\NTZ'a"Z%d6`C*Qp3-80Nr<0ecWU9E%g>LFI*`2GZjQ-R!8mA2gnAbr*(o8)'!GAd!$eVA?Ui>R>KaWSk=MI!^oFZjm$uJp +a)eq&"n!A.e_&V9T$._Mf;@a2M%9dbr,4\83F]L>2&UnWOFD$\fu<2CMJU:RMBX^]=jNIZV=&G_lul<< +GNo<7?@,N;:.B:BhAgZ`8X1k6KraN+8(K]Gm,?m5!=U9f(GZ[;B^8n8!I*gk94.DeaC^GZ=rI7"i2RD1 +n/g"$PNFjZ'Eo'`5RO+YiXC"uB9OlV@d(i>b1Jl2%3rkh#tg;:MnCeq7So.p1a==hrJ3Z+don^mqIQP[ ++7IIgo'o`MKR0F+"N?',NiHG]-J?dn6%A>jV&&BmRpq<"@V(%ML>usA[F%XG?YZ2Jn*P,?]0CnAlHr=5 +A>;p,2,`3b!tIu`Ki%)q2@%T?Oh<@t'%/N;C2TFG`KpY4eiA4/)bKK-$VFckIAJ",p/6CX14.u[BA)!& +e+LoXfcKUi]^4g^rA._B,!,Zk`c50oqP>`!^%\Bk'?s(E.[lKO(O[A>QXtp7\)[5rC_$*sZHQVl23DRU +!-Qlu6MCbA@0c%`ZB=e9i3/d^lmqa"lT6NOY1`&@.qb$2)/lrgI(RLi[*7mtZ@ulP.+Z\<<2=]t+1KI9 +A*0Kf3R=[Xq?oU*MnZ!3m\8/u4Z26GN%]!i^ts'5!Z+TiinUmJXNl"3W-%$b!-!!P!%>C\J"cENFq:05 +m>YdJV,^\#0B?n!lWI2=TVVaTgsQcA9-A24#8N*PETjrXgH1]I!)32j2SUS3TWm%T_Ro@28$a@c8CS0A.J[qE`\t#$kH?%d +P(W$`1rK_'c+:+KnaYZ^E>56+*:?$M[L,-r\.n/$3-PV/I7&mI9IN@.J:8pBediVT^05sH%IrOknHNQD +6nBBKNuht?ga.oZ/ZFmS+VfP].8cX3DL>$p^lXG]W,IcT[:ju'bu@YiEXL;5o-2>d<+Ij2De0q1Q\raP +/?)IS3!W?dOE2Z^$`.0#`UY>ZbPZ1kn0J7]S!5JLQ]d6-E9'p%31"OUF5KlXQ'5H&ZDs(/C!E:%D?.&D +=)4(;L/_\0RNiP_=<=,N'Al)*hXaA]Y,DWu1*8M*[==#,Tj*E':qB+QS4A(ao&\cbiEM4hObN+k056YpnQMQHB>ckTJ\ef[s,Q.8^UqC]97$Cs +]'(gIs1eR!oa].hO!H.lOtt>kIlk)h.UkUANoTqbndaPAhm^A4_j?Qm2u-8eYj%)Mbt@n^n.'9?ruE>h +5U&*]I)l!Qr8'NdpIpJsm$LP/G5`J*O3F<]iI8T39jI)Wr''W#,NIZg(h(kBZeK3t>=bDsPFsjhrGXo< +p`AsSId\c*1ZY'AR$RmW0rJ]E3*&6'3mHZQCD@;;%okMaD$s5*@8AX&,Q@+R7opA%C`\kM< +SFMJ>^t"%/2b]eklmLTa56hE&Y]'K"X6O"P0'%W$GqS0>66=33GD5'F8DX`:S#Eq.2+MmL4^+%Qc2Ph` +^UtDg$CYe5S-G#,paU[MJLYT1"?pn>rXp:ofmeiUS55MR(Z`dg3A[,olJqUVhjR!Z\C6IZ\j+YR +`n-u.WKf8'28bmQ1-b)mERaW?)&J/J(Hrg$[/-@RAm!Boj-Xi]#gSC8B0P?Kn+%?'RRPNsden/]\"o-u +]I(lX>&3sSB?"^&2)O@DsIb03.Bf*B-Cfk=UU.NY/]1`*iJ&)0Yhf.?@;V(\5YG@=d'q +jIKsF_R&hi?`d6F_Y0k;:YU5;9iSt%mn?V,H8.k# +GpG3B+&Z@WZF^lC +2e#&7OVm(\7k!Qh7g&GM*:i-%Ph +$DB+@\6G[^Dlk@^j-L2kK?ehK`JLe8R#W3oFl%@aI)a'^:@IuNHlG"6+Ln,j?@:>mj'0`6@&%Z9ZmNLg^J)uJQHf0pX-t4)aAJj(rgZ2@r`960/g_P53ES4P/XCa\)oE75CpDc] +KPN(*)ZdpN1o'OjT7p%n._[YMQ56FhVJ+o1fRNj_c4#2@p0.XqC1_S#H@ukuJ!9`u(`u8\E'5dt\1o"+ +bcqJC^md3UmJ"14?qJgZApuIm:J^6nA+-OMbUafl%hp6�Xq#;q_t%Q\[mS/F$s%B!oN2Lfpeal/qeqe,"l-,25i) +2q&E\?UXs4oLO&)rq[U!`lAZ9Nq/WKrZ^L7,O(]DZ1eVD@5eS.)&eJ+ju$0-8b%8_N&un/$A3'PQ]4l$ +HEThMq,]Z?>+rnT +N.sAp#ibb.`KS=GUIJ\!,+fn4P]?9pCGk])ZYgt[:MdEhjV,K0JI:j=?eAi'3`B'SjHqgS`J%I@6C1Y@ +%4Ci\BDdK"gL.A,BWs';rAVFgF2b]U_RC#/rC[co_V(`ge1ieud,(M[+!![AjPI`^,P0tfs. +\"@:@B.a_CS*Lj)7%05qqi7';]f4o#LsZra+2kS?#'f +f^le:&m$_>Rks`&ofimULYeqO;,/b"F-7kd2nbF42hAn4^?_\E5of.=9'XVrHsrO==JUH(:HZ-R9QjTW +6LmG%h#l>Wc0qD9il-6hd[lqP"L&4\I3<]+_"hj-cG1F9?VGKspOK$9oF-l`Ch?-=^MVcXW3gq%j2-Kd +F*$8RXe3_)'d_Gt7#$H&nqJD3fB(Z!hQ`f#C&b8J*&L1ON&@(jV93-l52432Lp&P_A.+EM3rM3m)fMo6 ++m.;!Y!IoJ4HkLc#q,l@_k_DZ5/7_`34;#G<@NK3@2sT&rsJ]\S#OIPMq^a@8:qt4n..N/f%M%R:SSL9 +h?^uG<6C*cX,3,q;lW/3,Z7n-Wu/ZHNoF);ZqbYMIQ8hr[$(Z)3!/%g/bbMnEn=c#(YBL/5tK9U3rYhL0S +1tNBWh5^,1hf34n4Muf9[rjhQ2''WAoibk"#.625RPa>Finu&k::,#4S:e-iXcp+IfeNfoHT?2uhSZ_1 +cNjl\A%og3rHaqtT@"E!rkY^q;6LQb\0>MKJ)a"WqP&-KX?8IcJtaYl!?Z]=%mAQR8Q+st9KB]h7s*c' +Ed'64Y2o!hhHS-.hIU`hrX98&n#Y.:6]dC0r[ach1`I&/pDMA#UXbtE^[V%Y%*g14&K$U +mOf8[OPF-2]^0Z_D9a6bY4_;NZIc[`0ZRAnBk7>[akbLHEF%ubXXM?J-,-52Fl[Sp1$.igZstP/Q_^jh +>?9p+\\#dsjPmSG;k1n[Ef0t#gSH[nZcM9O\\"'odnK0jLJ[D&pkQ?DAA>\1?/%kWEgLo5>ja4t&fnNp +2Ku'`Snj$"WZ4=8jR/JdR;-.+%)Def(4:h1M$) +bM>)-+$:U;=J'\LAbq2&C7q"*t,jY!_J +]A25%[&)Qc?E[#iDL!i_GB`5AJm>dQr&o:F&'fX2jq2X#=l57p[8<;1En=rWEd&&JAM/0KoCpRWHPO/6 +4K<\NLIY?hKnm)7-2p\bHiNoUrI%Yg`0lL0;%R;ZGs`UAiCc:QK(o_3.pj,@&&7UZ*oD=ba,>Ks&FMdf +j/%Ig!`Y\LG"EH@](g\B)(qG:bcFa8AEo([Z`'sZP:,s9!"H=f`^MXH-X*"RJuIDRe-Et2/Y!#DAcn/o +90#Oc<<=DuDYt,oep-Z5\W))]1<^qMoTkOfht0D/[-6IX>bV!Ih2B[GX0i6WQ?;*XI84C"HXVh_6Q[nSEoFZ@G/f[P*I8A8hT+%tFlPmY +Q#AUqMF(A#,OUc/^V5X"d7!Slcgc"7n,/D2r5FdZHol??.ks(% +;/AN_i,SF#W*b?n(-3ZcL?0&_CqRl`pW@\!?\Rr,`nS&D2+%+V@taF/"qE*'n\4$VlK'kA0nj88_XcLa +duS8$ccO4D[qH28Mr#5W7f)/@3-EK*`=Q\;[g_.G,1u>7.S_k(2T.di]bb>Fo\BSR7l\7!P4/+]G"9C\ +Xc6VBaHJX]ZfF`s+Y^or^0;^_:s6o!h^WXl+hioL>G1KAJnA78KBN)FC=\Q=?72mY`H;L/G8jYH#71tj +o\BRGXqf@'-//ubB?2srs"3mPQ`HC!KY7`>[?Gmp,0>baQ;jY_4(^>lWJkJrA@b8`(29)#pfm,Ve+o#O +\%ipUL'rPIO*"Ua-=+sq#BBSJ(!lA'`mLqT%LU6sNn8cIql8q=#fk)6lJqdaq]m,Vrsaj)*V-!#j:SB^I$( +"?qJds+mFtXhfd3@BBK&\\_Q6er.nn(WEGLN'gt%HN^rA`V7oO+2?$ta.a"8#P=L1=R/,3O7qkR,'U@= +!,qEW@[!kS1S31Z"`B^=61Q0%?4g?+Rd5gl +1Pk5OZ$ZiIm@naJT#$24?Ak#iF%hD1_sQmM3mf:!P#8knC\SHmb2o@ur!iTLAu&7hC;*FOlSX/HUZ&9P +q;_"oB>gWP'6PT_fWFnh*R4YX`!Z"mag%Dc&[+5jK?31E`]r9gf4k2=_g#q=Riqg +<3Aga!4c=BA?t8Kj.K]GQLu,.AqBdn,9:E/nOq![Z9L#"/\YDKgo\D@M@mSJ-d_m9[8uf<@rL,bjgts? +9(#a;iKa?2j<$gJ,=F2,07uD/EF04S0B\W*U3"q#c!JW2cI*WW(0M@L +$aI0ppG2(TdKC-M_:/iQ]cH,[7f3nLDY7>l-KX#V(?/32n&YW1Lo*UjKgbBQ>#>:G:h)]Sc;gY6ZGOdk +N;">DeW/^R:]AAEWT@FJGF..X$62pA#Z4+^q1YodqYae3iNDjlgr-H]Q(*#=4k's@LEh/SYs=LV)[g.m +N2TgD^=p`ugf^1WUN2Wnb55'PGC@h1HF@hunj[ED%@./SihdTch7P[VO^tXZ<8N]l54+;f2a7T."$6n, +'Zh-Q:L:,\AlL7kml#]NDWNXG2Igls5lmCU1H6f/)t=p#1"%V!6mHWkg3XcW6S551g4!hZ:l:`42O`GT +NphrrHD8sA8g.Ko\aO&gCLoBA":orMZ,M"cMI\P`k'A*0Q\$V$]@/V+k0+cJRAf_d]ZJNi9*SU'f#&I_ +`V]*:Vg#:V[IUslTr9+/OM=aGmC5db+O<%/>T3o*SUMZ>Lsj*p8;o=f_rjnCWq[4uN;$(-Tr@P-6=u@X +)qfHPo5]83VGfU>%pa/G#VjuCWT_abQ/%$0oYRjWe1?]eP[$1(0"gHJGf5.P9(Q@Z]VEkor8KK.GF&)G +M*lSZCWI4O,]CgFO:JsTaeb9;[-3g2Hst%Z6H\6#edl_gN\.h`E(qgKHdR7c`qUk*&(:>mQ7N&rgHj(o +quSOk+E-+)P"5/f7]@!gD4J_.FZ,=b#X(d=8fhj*H,Hg> +10ZjpY4i,@oMna[4j'@Qrm:C*ES^+R9R,>I`KuI'PbBC@_q^9t,$)e0JZRLgOh2\L,Nul8'-fS=rX)NN +H>cVW?_*-_R:1[9"#/i"s5,PuUo3^=*#n$ij>`bo%8]X)+gA0l?5$Y@$YZT+q> +ZHoeuri(%MNAHDPn(D;:45=`eFFGW +m+/d6KPb;!lRIfhXTWG21Y +@f-Q.lDJGq7V>bB4D/MFpQ`E=^^:PH`JO]VZt?5kA@D(rRE#+r/,9YYZ(!2DP&cZ-_h/b0QS`;=n*RDB +r2\=ohBV;Rn#spqFnV!s,=X_]SR$>6p@q_U.6b +`(7(ib)82+e@LibM-7N]pGY3-K]Q,KpJpX1:\qio["70)j)EJeA$6?]=lWU(:tQ5B.(tE +Z:#O0R]Oi.@<3k7*.f^R:]Blf%%1.7/#pRM\L*W:^8[`@T=5JF:.4Ls(?E`A;mJ&*M%R+!AkKM4F]%U= +YAgeUpK3[=#g=o)de2Cr/Hg\oQAB2Rs&i.fg>#77lnFQ_g`g6^^B8[gJ,UJcoDbVapn.$0hg1/9WsR7K +qfD6^[^9e#X8mERgN=-5F[YgRi8Q_Leb:18RT$F`8CQTGGAO2ug-X`D(`bJWFKm>)8H +*jP^5pUA8&nee!#R'\>N("[SXc3Su(n^7'r`6g77PR8\M+kd^.ZB]W_9CmV#*TAJ:-ql)P^D,f%hBdZD +Is"&,H&lq/3Vp?fTuKU4(#:OuMYop^mlU75>"-Sob$0WF_j&Y>&`IS"qr!2G/uK"j7clhdX_@6bQbUW8bn?Yk_iN?K'cgmoO +m8UMt28RFmMiNO8U'I0RZsP.&bWY:Se>Z`#m4N$&ImkCE+]hr\A]-W4$QGiak1ZcDTk#!'7U?+"KpcUP +f'--=[tef9'!#?-(V\mDS"l;I"@Y1F@9lJns[p"rhuS`FRo +i^Q&o1<>7K-1,fP$hM)3guZHMml.8\e0^WTA$EBR[H=rRW.EU0'80sP+32!YTKZeK5HV`bppE0K8Js%O6?s3kUC$ka])/ +-A;,I0ac@\p/2pC!^i)3V@db/c5DkA,9Jc?`'\c)cO@61c@a?P!tP!?52uOXX?2Mt=<>farDJq%:r"[' +6]k@9&I*tN(67ooK7Jn>lj7a4o]/09jHi>/$E',>1dYX=ir#.6E`hf'$t'!6>[iX5WE-G'l[&"S5%rK, +jS.ZgT,S;Q:28:RJNK]6@Rch^R@6*NN+ls.;Q.M&L$[iVA#CU-4D1_:&Ppt'NKsMgLD?Z0/3oe+Ibb?,iL1>YA)jmD +'7i>*SmR\94U9t]jsf*F?D[1^'09MVB1er[*aT^$#69psTK`0^o?94;8#3V.*cK#gr^l,SR>;buOeNNE:k).=Qj2jNMRdbu&^\eXY\&C/g_,Z#lmtGM>eSjJlBe!.qlj1-i5Bp(nL*N7mNml^1[3`g'N9i\C +AS;0?T"_'C3_^T"Q]Lk.5;Q"C?_*H0@`!@Oo=SVf@tg1W-Zu0/[@32LOCaGdo8IUi(rLkX4U[Z\A^/XPR,cEce%_n$-Jk +8[WdQ,tPumkg2E'8"m6"G:0ll*:L!s(/!fo9;(841,rjZI>KWq>*K*1M#6q;m8#i +jFb3m5#j7Ok3'b6!eY[^"7OSDQA[)Fl5 +e$Xc22"sWn3-MDX;+AL3_CXbgC5#f\9;iRB,3i??b*F9ubj>4hj^ZR,E"osD_,6-&("We&dGE3@O_Ek' +$::F$*)eAdk.%e8=O'4TrNg3$:b2%2d%+)6d*W2]rptfO +]2b:3$ca5L_V]p^>1W<6fUoq8L`#LENPO_:B"bVL%I[EFs2uo@?[Y=nRFB1[D`m)5EHS7Sp'-HCi8W1L +@pn_sCJ=Ks^?)Vl[s`NU--&@"Qj6s<^?"O599M0G\(,8PY@ColSE.8_Ye2s)ICXOrU=d&!'! +WFM*%B9tZM[>*FQ?TN@%Z?(9+$I9iTICX(4LEp$Wjil^%d*Y>(13;3:CJr$L'uu.`8_2gKd3XY":p2$6 +C)qptV;cXdWrQoFWaZuXFKQ=i^ih/.(A]h'1U^%Ij,k[mU+ABa;tP't\X +k#10"!kUK@5B'.*s8>$N2Hds:'67a->%]ash0hu9o+=^M3Qu;=_En<@g;T8&\Aq^R9=EB.3p+uQR5R4] +FmrX61IBiR`Tr)DSiu]>(T2T*e#CW&VD]V'NSVA_Nljs"C8(BWcbEt>rnh;"5ntCC"1'VenD`g[<7^.8 +OEH>b>-k44F6fbE-FehhNA0WBg[-\2dM>]#ABuU7_fK"Z>*6K%=U_MLA53Nfo1"m=?.B&*]'h;3?\ +RC.[^*6JK&pR55i]arnE+<(T51cjs]Z+m&\rB?7]><,T!;Oe5lqq+H9d8ag;X#5H[T^QQcK0sl;l6MrB +*37qLE2NEULt]=]-OC(s4+#bN/eb!_(sUQYV1e1GVfh4:aBO:$oa&'db2V3jTl)>8:gg&BTgNbX`-`g- +-.B3sHi$e9!I_AV=t+gJ#<@_@,ndogC#qmtWn*$qL?HGd&][3U4o&<)\_ALLNd9ZLFe"0#!tT(; +ms+gPqt#'mqMb'kGiSd>NkY['DciI;#PR>a2kE3NdE;>WHtm6aq0.5ZZ)g`<>#dG2\9bP;e5:O$#4Q5( +[B6(S=,naM)o%W9C!8.TC,hM+Ic%/>g`>A,Tln?*iN7rMql7N>jOp[C`kFW6@B_p,U$A=PMY\F\aH!X2euGn`]fk?@>_Y99EpK&X>g0X2YHuYG^D%'.,l3\cTk&Yj`ndt +ie][bm,7V*WR?1t,I0h)p,T9VQT(`_:5nO0U^U0c#7n^f'HHO$8fmq4D//>CB-7jti,[@Qsf"2tGIP=`HAlK!AKqG3_L1<8D;VM66_Y(p1<$NU"1$n^Xh13B_k24rF7V +e"[S]:!t#*`$*+8`EW9`[C9[K/cKS$a'Y2.pjk)Yg#@i9Sr@ZmT@fM +@t4L8=j#l6rYQ%`;3gM8pcEFfW`,sUe\?(b/dBX_^VJ2,fCSHU"g(UTrYOF?]:/\Ha511`rf6jEN&ImP +ftjXtqaF#GpP(gP0Id'0m1VXoTATAZ]1M$%?f,?(#3ph"CbC3T4SV@/O)N\-TIRi+:!l2+d?[7&De6nV +*%$*\C+I/_AV!CIMKZ(=B=L002j(4mJJuXI.6j<\7B3!k*BdlW01-CD=n@<5GoOKt`7'V[]ABo/WS4?R +.`qQUC-p48X.O'E1u"/43j7*[PS0+ub4TWLmsTR,Ep]N['^D:A:`'G#n]OONS"+u%iYA+D)p46jl=\\. +*iS$kUp81F[HUiH*Hk81p\M4lTk\e06RqD2hu#iu/t1dWo?Y61.*a^%&lA[%61KX^F`B]Y5NWga&=tKK +ZF=Gi:*E?NM8_=O72aU]$m)S$#su/[q=W*Gn=Sa%>9<3sIrWf>n:XkTs4Vg0M$E8_Y[=AQIS*)];Q^Z2&Y7>;%dWU)!^ +NSLLV*'hg8pR'n4`e`s>;TkMToC+:i&'sOS=@ArZVH#OrBn^=i1C.XiF+26KjsGRLlKslpnJU:X:V")H +-9,Hts,I>0.PU0e)PT>26Cm[@4f;>t_>=VNc@J2kDFmPo7eL9%`Y1P+\_fAj*K8dpPe+q84/^peBl:I$ +.E0*A"4,,:,W'bT.e">Ud!C*!TV%g*_kd>,gO(D"ZWWHX/[4rbb%NgYQW@X9/WY(]>(>KuRJj!SKp17c +aJ]Hj-_*R8iPdfOD`HUorkIL:2R"`l*@$Y_Q1DaE6k.UJ__c?JFfck*Pfd*uaAAmHC:On"gLHl,G-h'Q^3h@eM?ab_>dN;-#10<&U +RUT#!;>W>=855Ub)-S.YXaD5,PZGTpnrsS]*b[E\[Y,Fc?V1^e +WEl+&5[J>\.-"s]rTIU%Ja=-Z>*3GSZp73GC=31&pQ(n-ZQ(P>'NuW`[(oB`A_&DqHo!NnhRdcW_`J>[ +:gCW?X09qQ)FnIlm'7U7+R^QL6'6V3JNRikOf+eqT_+>J2auu)54Q>(pXeFJf)c1)[GIE.['$2.1qtD2 +CHYiD]>fpJ&7%U1"I9f7Q57ge8dgk/b?nGG,cq6k=A_e554>hM':4]ZFnne2IKU*c$Y8$fF=gmqh4Xu\ +oh,ZPFtI+:9h,SI1=?5LatAqp&>aEkln&nEOTF'9eQT7^T`n'>fVA\.b?ei_EN6C]c,[u18a\rZpWp[E +^Z%>i+XF1kflRPAed%2X'\tSJA_pV%%$t1PW'9)(?3.M.gTD)SJ%tsc*p!.VI(S*Xn+>/)Y>/\;4k3J@\ZWTRY7^EF$3:m-6dO.1I&Uc'/\&H? +IUG]_,#Q!ZXl/7-H&'5F4aU1_@bK=`;p`$eaeu:*N9M$plli_*lY2qHq3t?)6/PO/.UYGuI.j(]T%,3% +"sV;W]3;]-Z8heG!11sjmcDAUH/Qm_dD],n2g<-*VfJCLKh5-XN[#E-r +n)DY#LE0Cd_o)(J&!8$%,GlRY@/>j79CVie9L!R#?()4EYMH;kAQJMM!;3AX87iO,DLEpWYKI'WL2BhE +_E7>]8%EJR>kK%_L

-UIl@PMAS6fh/iuEF#VB,57aKX<*SBQ67/%ofA`uWrk%j]94%Hb^6Wa;q7bfU6XJs[gjm=rO +S#-h?&'PWniB+-df#ntHhIfDQP<2jHmk>n\>'%BZ/BY^,JF%*W_]K,+fCA7QDpldL2^TMBUA5\E'?>!l +2-G=J,HdV05.1+>NG2(LD6;\n;7$Y$Cjo"=Xo3er6&Rt.2i6hO0#+qu;NgjI^OLGcqVNBIfej-9r#\_C +nULQi7YmX7dmSO?:/-FtYWr/Js2S'es1U\jQD#1AG=Fui4.aTMCl>:q(Z!=^9"`K?pfkb<mdKCW(^Ye9a`_C?H +bVQX)`cBYP0k/.jG\$<@2sr(i+Nr,3OV$6V6oX@MUL>Q/S]N#ZUX'$f-<\A[a1Q\'(qVW\2:kDBqi@h0 +L2hDV66EgbhS1\d&]Zs,C$jcGH0a5IVKlu/DggZZp=3p:0ntc9TRn7hf,Zci9l[ua>84urV;.#7OEd:r +_6N5O3fG4QGhuVroZuQ0\,,!)(Q*dod>Iht5o8=Q_,p2%Q\N/%'kri)d,V:1-%(5o#iA6H'2!pVM/8jpOR,AC=jMcOCr6H4P>X-T,YA@=HV@W +;"`T@i:-11.bY"Dj;4opmPKU?-!D\J4YEdCh%T=mSkB6!j#)\0?Z'JV3:_dt[1P_6b2?m/j.Vuh%0?=? +Z0KO::0^LQ0Z1J$p1pgEh?ms&8(EJU7$9>XQ!]XThZ;)gl5g'OdS_PFWejPd^lnBO.[r5EE[@]!-5IJ +JZb,X!8B4"WIDbo110ccIX/OB"qT8s.Q;QC'P8r_.(KSR5Cn,DHcL6odX%-+D)-$RpHZCg?05ii^b'(-F.a>l5M_(^HnQ+n)d8KoV&rY^^CSV=Du\2K>IiLp +c6GGqHgV^=p`&'E,V8JYhkK8^=*T?P%^tV>2Th4M-_q8aBQnmP.t?g;Ua%=7[)-eeIBf2!@pU(*=X-0p +ATQe2i9%[KSi^Pj5p[mrN$HWRhQ=8j8-`.5XV-4mTWdr(Xh9OF$DQce$VDZ,ccjlaCbq +2ehKaE74P)1L:U7O:,.XhCA\8]2&;KclZ/NUR9Q)Pdt;OW^MsXh.%8\%H4`jX).7MXM]n'6dr/1At"Ie +jA#>?gN?39J;lb^2R+r(.Pk1.78tPpX?O)fKIJjKkHVEGh8e@n82B,OPP=X/C`S_f8$)kLAmaL#R$95J +1ckN\R.DAcMW"RR#8PoNNYA`nBEsVin'6'iF[M3k1^4D';#f/WA%AZQLMcJGfK,3\gQ^=%iP#'0,!MC& +.6&T(b9-ZB)7QLp^TEILPC44c4&I0?9D722-n]d3/uUA_n5rI84Vf?<>,P#P`j&/d;sTCY*C@WfeU^]. +DT@gSg$h[DO8a3[CeEj7kha*ml`EQlnqKN3kkSTl(SC(Bj0j,Za9@S4?-[S6>Whe8 +>O(hDHPW-kRr$W*q4uo9@mFh01'9gD7):p_8E)Vk?#fljP"k^uK.$=lnYCKl>fZgJ:MM`C3h8X]$p'%u +'pU%[76tg#T(>CBCpnW;#_!7a7eKLtL0umgW`+Ko=S2V:$N^rK]2^khe!)A0:0Q%[?1&G0b]r"-rEa"? +Mm&!ce0CZ[pi]A:QtLl3IsX9G9qK%e?aZ0'5J0Ki-0fEM+cXKG3E#mRkRd4M^@")YB?eo#S%`8!W9oO: +`HLO3Z"aWO0FE:O>Wj_g')2@A_^kTu*'!o6n[sA?*UA(P6KV./+K%^;.m82XZ2(Y/%B4(9T@2PUX3\P" +oS@c&IpjjU6n\rB2Bt4Op4J"@iqr$TT+SF0n+[f0SK*3AcpZ1P6suo)"+>XWpk"pfq)=>srHn#.oZ1iG +dWdLQT5`6r4+2OjEaM:_Op-\MjcW!rP-)Dh+72<4a-(c8Ar*fARF0_b-HcrMTlDs_-JP:=B;o='N","\ +L2AQ_5uTPh0uQlc'(-B^mmng5S:,NjmT/#9_7C!=mt_Bi*0%FJUk>^@F;W]O7Omq'UJl--W6[l'8mYk> +o=(t!n2.nd\1:=EmhAd4`c0["Hi-`CN=*4t#4K3A*eTLc48oBOUKSUW]&:9o/L:"]^6QfQ;*iu^''k"/ +qEdJd@2,!u?ZoBkp%NL?E,ISEY;0l=T$?'>ZbJmJ>90UVL#RVN#B@$;VmM=r$$u?e3-Y/PX86YSTqXS? +^i5!V_kOJ;IkWL[$0,4%Tg>.cf8^;_\+%1O_sJ;BJ(EsJ.!mR"i'qL$300tWhHQ6e`P5T]/,(*i)MRpp +]%qLiO'13K+EsWAs2(Um^V)=n)RVaV^aun!%fMK-Bq:i'b;5O*02RU(=SB:SWI/W1n'jP:^H+Mfg>XU5 +SdG@$o&ffT([l`5%On@H^>hlOZ'6iMeoNO1i>D8F>:6Q?ar.BOp?1QX_bNkcgW9dY6;.;ma.&Kji6'!L +@V$\:WK!j?6>ltpZ_Br1W%fe:I[PW9`:EtI"o72FOs';O7Ob%7ifGm@,S^1l`hA1fP1^';]n[*qW`+a; +EXL[qrOOG<]dGDE<#fhB"GVT-S^[87-7^Kc"tW:!`5QpkTQ3kf5^7Y3SkP$foA8HZo^pZ7a,]mb'%/5s +noMZ6(9R5&q(K93NVAH-4+L\g^/R79jSa5&N/@J/O-K)rFPp5k9'h[=n>7ie^,!+&oD%e_2A]?=IiBm7jYZIr='fT#hk3f!r:chXOLAB?>9UkonCDC*]`fj +3[TpRQf<"u2s?pE-(ecg>KF&ncZ5=!k(hZqdKuF>un-'Y!>?_2J/i +3)r*S(H]U,a0dRD*etC\G^NAG`7dLr9WTe:iVBJe$4[[!MWHL^a8+T0j#_'?EbS1%JiA*Ln]CSn9^*(' +i=*caJO:+7q022Os,3;=[)VT)a$\FnmZ`=Umi0DSTm#:1fp\j.OJBWGXDQZ\]93N^SrM6A_*(iXAbXYW +aH\k8gqe3Wb*K<-mlVK?3B1[.8::cV=gr%+YKWWR$a'4R&+Gl#A3S9TRXB:_pQ\bkZ^1%EDq^en$K".n +QSN:nWhe&gs"[2T%oSs2D4>1dAu![;,>$K/D"cGWVf(S:J46S2gLPAlbLnb;%l\D0clQNNOsb"`@0eFK +5q6Rj[m\-Fc[1j[h0F902d"L7>Gm1pq$(/1-_#%WdaZL62_"9]_(0VVjm5OtRI>T+fC>l5;dlGG.fp[Z +9;8$U/#!FEd:V^19^Xj6B4&/eIhph#`7i:cVVP5"ZdNZT*"erK +M)66[d&/Y_;4=.1*i6+qQX_kb=V)ZsjrPgGkoXP&lN=8.tu,gMHO"C)$`$f%QGm@K// +qq&[NEh0=rkfB*oIhUQn2KkDR-+8qiIBcP)n@.H7;-N)9T7=oOr86[cQl5IffmPlmlRCUfjt52QER<3< +q9%'"$eSS_D.Zb,m9]J3E94El;E;Q'0P!b&'5S_`f=Y;:'d/F%GLf*n +&EIA0*,-=k)lW;?YE!eWpZ&SA!F$2M=!(bThcXC5qO?l=Q2V',@fhu$\fb\'YU+53RD6`*X.a,'D=kIY +:!3UHe?'VJVm@l+L#<[VN8)($ZMfq8p+e6q(r@/oojLuF=b6kl$m^^^qWlKIoN*Q+?2ui*[6Z06(9I6( +Z<4+M9:DC/O0h)edR@9+W?r"K)RdSL#mFTCD9W8T"$]?'*tEtf+XYR_%Rg0f*N^2KT:sJk\+kjEdb"fq +Cgmq@4@iK=/o7@US>+(0@gK_#f`D)DR)_YpSf>a_.P:Y*;-"X=`:0bZ=F2AjZpPWV'MjA[YI'i/VZiS+ +.DETa=B.[KgUV:_HS\_Kp`83l>MFL\hChl;fTO&t\F^553lcnqQ9qDAMoiUh,Bp13/#SLQ@1=AX6W*r0 +J\m&A[[&$+`FRlM#kRJcQ"gqEg4R6u&$C#EE@\rf3.:*6oA=uDe>J> +*E)?WT*ecr4M6D#d,DpUfI+)D^XZJ*G@ncD@Q!Yg3&AP=Ia)qbpBrK9+66>:ETIMVP>3IFB??BFnEg,o +]]eU>2n\0:Hd-lC3"j<69rU0FGFW#RQ#i2J8JooGK-O)!ja"t64=G:$g.pQg--RG>@P=N3L>I22a%EOM-X39X7RY?`"r/"M +X"7[q?Bj=9q\l#;G4Yr50DVtA6isX6V>GU!Sk8=[aQ\u9@T>7F2:MFMChjIT)!pM,oa(AK21noTp%8q, +=K>/;[tu[WDMGla<=dY?1;Ut6UU@n.NHJ!6SfBal8]f@i.pXPubt,):i+'i]JhrLsECB_Gn7He>/2/O1 +EG$l_Dh%aFf'.*\#Za=>*osnaZfY"kq1WIXJN$f0UFZjmR;A@]IIDrkl3<7`W946nC'AA'JdXYp&lGN\ +6Y+NMMbK:#7UL."bC2G94K/T+j0+\[:OLP#ci;"KQ$o7q!SP@=gs0ZD5JZ:)ai)fkXFc=f0uknWS[-PP +dOIlPI*\6b6M>5l*)\:R>4>NbO^'j^3hJ.^AG^5NQ@W%pAGSXCq]P5];6d@^nY$5\J&gcp&FRJ:4d2aS +b50,#K"+g>WOTZ1dAItbaCpd?29*L&=0#ABe7+Lc54jSZY07kUNW?o[etuCjj2,K +DY`lZS'Q<%e4i-E/QTJ";iqfhZ5C]GojguSZaK5Unums0Q!=4rRWZfg0$XJLs+>"\4/V+Hf5:?8osFY_ +\h3r^]a69?VNj0-InNS\^Lch+VnG>J2V<`ZMhSIh6H.a0bbiakJCs?*n";Xa/q'A,02/jN@o8e`esm;Sc:Qe&lk#Q@GH1X0he-E7$7eRgmK].Jb]#o.6-RZk$On +[iL:smjhQnLle`A`AHU*U.bH(bPt#=`#dKTOB_\hHT=GsO+h7DIo+G^dZRi6/Q$--nuqq)q(iHP=T2;Y +61\Xb93*'srjQlM0ta"7Q@B>oVRM35nio)_OZcdAMISh$J"qK&bF_(2/n5`KFX3'.mV:!!#Aa!a7E=ts +<,g$qTb+&)rX\f+/`/fgX<_KT[V7\ce1u!,bk:/VEL_&EL5"90E8D2:l&CW1IUK9g&YEWH_ +l_[bO(g,_%2ekfK:(GZ3kXN-o\SQf6LSu>^m:;KdBh`6Gd_Cl;Y2ntM( +lT=?_6l+^IN7liR&,,EQ9_)j=\".8O60_N%!7R:h(YjX'%5Xt/%UfD##QKJ"qGJ]?#Oi'GkY_5\%cn3=9I9m>:`!^j%RbYGHF<"1X65V>e8L`BlN$mU2d[X8VHN7Pl'2 +llLg_Bi360^e._s6't.DJBMQeDN5ck.6E8*"@qlGE(geZba`Nr&>ne[pE7]>r[Bs6.B08P==`[+Wr +?:\*V<^l"Mh1It?4:(ZQ$4k!A#aTfK=F'=Z&8(J*C)UKs/9],tX7&A'\*(HZ0tQEe*X%B`-69HcB(X_h +-r-TDiPEQrgK'Mo4qU0r)d\]AY@"J%b9EX9VNmO:a"j&u]6D_?@b.CH547KY/rju@tpHN^sBDj+]@ +cgNOiYF4KdWqIro$I?irqo[Z]/+"?YmEcm6J7.qIdGA^rZuaTgWR&;&CDbIc5oJ70&gApm^?HsSZ[EH^ +f"j5:`L?,qWh(/u4?kR4^ep@Sin2;XhB^>Qfu.gEMf;2%0Z?HZDGs2)Vn>5'\_7XR>o +L=Ws2GP0_fY]-]K^[+4Fl^YT2(R>57L!S?B2.ZT\a*PW1glp/$5Pb\VZXff$lDJ"a:k6m,A,1S02mHLp +4*EGMOhKQE6&KJ`4a)^!>[l9O=%_'Orq`s!^*p9"DR[aq>tI3lfr0W18,\mHPoAJ]4D!ZI`PB +C=PlFbFjLE)cX[UK7`=7PJ3hP;HgIk\D(+W*qqtd>r\X9Sq"fNr9K>k3i*j:@-rJG7a1N-YLjGj>\In] +7r2k#7[UZM.t%iY&KBH/,@7qVfb/DaiYb.kG3?NiNb7B=RB.F6@6[,c5"Mte7r8-"f8_hpG/Wo-G/VR" +mT+_ug(@OB)T"l]i9p;XBd3*.jsV1m"c+9p7WLH+ROse@n2Jb`fA^.>H]&% +Ag;K;et]PV[f4FE:FVUAlN";PnAG`3<0e^$'LBW1.Z$Ns,C]1oGVgoh5WdtjL\jh^k*KOICoG])^lB6G +NubL!&j'Q]i7\dtpgu[keRcb%jMYh(%*HMK(d(J0@I#^^g6()$5PrdN6?^ph'Zi^h@c>c6";$1\_C/b? +ChEo@^DB5I7G:\:\\AlG(43$hGr0%o=&_jq83-VgkKU<'r+04,kOZAL*rl)s?ff\4pP:'`rXsXmNK7_m +($e&-%7A[ZmhU:6WR7J>6j=ZpC +^lk>TDc'Lj*tRo9g\?#&"m;d\^.k,"Tkp@*Tp3m9n;P-G`WNlQ)84>d]PaCV%r/blIGl'_Q>K=+H\k^\ +E9P!!Ho5%NeTQDI-mrG31pr]U3c`r7/fX^[Us'5<]%$ +?^ua`["35=e<%%p;5>o^^dKtk'\NdtV_li":u\qFgrnAP5DW+Mc3i(mJa'S.ltiWuCC'%3)1tb?]G/Rr +KU$$=L#EB\Z43+CA1=<8ZAgj$qY;+ +0!u3J8_e=S(ATbC>7jb&TZQ"2Yn`-H_hc^ld7!\W9-`fGP\Qi[6*DS +-++c(e94Nbhkj3..dN5NmOLHK38&"9+,bi]rLb7=U#R +/M_d3K:[=kC@1k!Zi'afO]/JIB?#QU3%(pXRKpe;KI`\V02(K7 +_fnXV2_1t7ZS0fQ8QMb!bM?1.6W.]CM*6\n^YatAMuM7`1g]#`8)@Un)@_2\,NX7_*V`X4&pr[R]]i(H +UR83cKccghUi]`MS+.C#3N!;WAGWYD[hOO-S]C>\N:M/`h:6m;^UY`aPWii4pRD:M(D<.c.l;44r(>3N4MVWHIn%:Pf<(hY/?tMDK(QoT.Rkq4%QKaYSO"@C@LQX=P'0[bdOIAC +G!nDGY,-?bUcDCbL2YS4!lg:[+ +4"cJZBmAZs#LA7`&]Xas^93:D?0E:Xme*8tUf@25kT(h@oZF.thN>Z8>I\R8En\R=9ng2ARr]!n)eaF* +QS@DVim,B&_7*\u$h>JK]d#uqj?'^Ak/f^L*?eULcEb;&VI!BWXab]8H'%&Tmmmqk)ndI6+/J9q[^.:e +dTU)Q,gdQ#HJ)@K]d"D-S0>eMH8p5qDDa?`7liKYi2iS1,l +YjGGYCo,PtK=B]j]WX=f/%m1\pJX%[CMhu\WOl?(7dRf^UAaaGNbN.<*_Lkg_f"$Ej]=cE, +Z&s6uM2Z*9m3R(*;/a+sHg5gd*26c+P!;qZAW&23V8Rd.^nL&6_Dni2#lVRg%(dHiP%%(#1WCM=GWV"h +U6VXeLa_fAGdVELp-o?p]fH.;X:C8`:m\@=)#AZD.K%i>>WD2IPmhY.t_ea$^&9=U_hd_pHC!6fB^.XkLmQNJ"E>H +MC%K=^MdqF4`l.[VC2 +6DiudpB'#X>8Z5^.`EcEDn#-&Vlr6'@C1eFU)k/oXsLPB`A;lFQ8N(?@CM;B8\f,RA'[2Q\?VUuN\0+& +U$O.'h9U"oq\d(+d.6j)4+]\u2pQZ^Vpak^P#^1;0@+;d_Gt0A"2'a.CR9)Airo>#t@:;=7$-Y7X +:M5Zujk1#!Yq/[\dakWb43h!Nnm%!:V_B\u]5nA'PJ"hFGri^h/^Ia6LRN)5.p!3`T"Si\5\\\.!j4"K +G_Y>5l/R!2Z]d'*QD]fqc\6(Y?K=Mr:$OlET#)C=Wo8tLH$3@3DL$CRBka9tBG&DXm+D6XnoW0WgQiU" +/=e=f7a[+AXSia@]K87T@kKtK4=B_;eBA^SsFLd(d +\M,V]Kh\?8YYQ1pg-/;uB1EN4cp6YV\8Bp`=UrW]_\!KW"^a&kj7H"c,KmFb"K,Iq`[C4`H$8b!_X\D, +jk6o\Q)6L^['2Z>;44bDahHBn`SqY:TUmuppU.3QY4VqAFIptibHk!P(c(/CFXul8Nog)Q=p;>2T]^uO +/=;cfn"Z*B\*6K*7qQu]ouMM7FnK/5e7/'#&Se$sT6i8Mp(5_2'3Q@&"(ROWV9^D^66'i\07c"PB')e! +@rRnRAn5^FKtV\BYfjm$E):3b)�]mY/=2&TW2ma/lC@`l5/:7&KFm;%lW1]No%g&FYr-QA(4Ajp8"P +UW`AA@eJ'PpMVaWMt_/":Ik@&e=#1._/Ek1o8W33r>V$(o[7tO)a1^ATDOu*L5h_V:)s?7-dh4Oj6.#A +^NUZuZ>.!]XjX!.4W$Ou'^[@`>YsAlO-Xs^&E&31R*%jXTIKtWlWLF/BamMpQr)( +5Gm?l=&ds0(t[ueQ2rZ,n8`TuHJX=)^*Gl==#tF$=e3,&*1cofEZ"KZORCb0OnaY-jr'AlDE7>Qi^qu* +2?"K?9:"P^"t,bMb8l4/q?'q+h'da_3?c`G0cKbgd6PpG.#e1p5J\(I@5sj'7iJDD(o>7naEmWqShR+L +4S*l`,@7rr7@^po,2jT&+%;:m]t@%1J[WcS7b(K6F32![)a8/F5Kg@X\,rsFIHl+Foh0IVSB72Htbl;[Ps5Q$;lYZW^B9O!0eruWJ.94iBmXgI_ +f";(c,cu?)8"a'mo.J1X6Omh:6PU#>K6ar\+W"RG#?l37MI`@%5sr]W[H!9W?bYr)\aBEg7h-p3>lf^_joXJ,ocje6-7Zhd+VW`?@S23Ls%eRb^mr)p#J7TCd[*QsU]^AV,q7-D4IJn$Dcoi0_)7'k43jW%eRuq\Ti3mRbomMf!W8,QqN`>4]S(M;gEu`$[=I1X8FtgIC)%>YD`P(?"^QNB58a3gh%/K)&\lEfM$a27]phnR#PLA +edLYI*EGPbor[C+oN8CD9^H?1bQ>56o&+;[h(8MYD65Y'P5_`:e4.of;<;M/m;`NXn2Vkd;ncg +^FQct5Q1V3q__PeI!TG<%eKL=@?\TrmIZHF_/,lXEaLVWk6CN><8KkoHkn`g$M(.%5X/_m +biJHkQ[^#-rpoVe;>LlA~> +endstream +endobj +7 0 obj + 68467 +endobj +3 0 obj + << + /Parent null + /Type /Pages + /MediaBox [0.0000 0.0000 798.00 551.00] + /Resources 8 0 R + /Kids [5 0 R] + /Count 1 + >> +endobj +9 0 obj + [/PDF /Text /ImageC] +endobj +10 0 obj + << + /S /Transparency + /CS /DeviceRGB + /I true + /K false + >> +endobj +11 0 obj + << + /Alpha1 + << + /ca 1.0000 + /CA 1.0000 + /BM /Normal + /AIS false + >> + >> +endobj +8 0 obj + << + /ProcSet 9 0 R + /ExtGState 11 0 R + >> +endobj +xref +0 12 +0000000000 65535 f +0000000015 00000 n +0000000315 00000 n +0000069210 00000 n +0000000445 00000 n +0000000521 00000 n +0000000609 00000 n +0000069186 00000 n +0000069664 00000 n +0000069380 00000 n +0000069419 00000 n +0000069521 00000 n +trailer +<< + /Size 12 + /Root 2 0 R + /Info 1 0 R +>> +startxref +69737 +%%EOF diff --git a/images/satrs-example-structure/satrs-example-structure.graphml b/images/satrs-example-structure/satrs-example-structure.graphml new file mode 100644 index 0000000..bc7f0c9 --- /dev/null +++ b/images/satrs-example-structure/satrs-example-structure.graphml @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + satrs-example Component Structure + + + + + + + + + + + + + + Application +Components + + + + + + + + + + Folder 3 + + + + + + + + + + + + + + + + ACS Task + + + + + + + + + + + + + + + + + + + + + + + + + + Folder 4 + + + + + + + + + + + + + + + + + + + Generic Components + + + + + + + + + + Folder 2 + + + + + + + + + + + + + + + + TM Funnel + + + + + + + + + + + UDP Server + + + + + + + + + + + TCP Server + + + + + + + + + + + TC Source + + + + + + + + + + + Event Manager + + + + + + + + + + + PUS Receiver + + + + + + + + + + + Shared +TMTC Pools + + + + + + + + + + + + + + + + PUS Stack + + + + + + + + + + Folder 1 + + + + + + + + + + + + + + + + PUS 1 Verification + + + + + + + + + + + PUS 3 Housekeeping + + + + + + + + + + + PUS 5 Events + + + + + + + + + + + PUS 8 Actions + + + + + + + + + + + PUS 17 Test + + + + + + + + + + + PUS 11 Scheduling + + + + + + + + + + + + + diff --git a/images/satrs-example-structure/satrs-example-structure.pdf b/images/satrs-example-structure/satrs-example-structure.pdf new file mode 100644 index 0000000..97d8ede --- /dev/null +++ b/images/satrs-example-structure/satrs-example-structure.pdf @@ -0,0 +1,835 @@ +%PDF-1.4 +%âãÏÓ +1 0 obj + << + /Title () + /Author () + /Subject () + /Keywords () + /Creator (yExport 1.5) + /Producer (org.freehep.graphicsio.pdf.YPDFGraphics2D 1.5) + /CreationDate (D:20240208115813+01'00') + /ModDate (D:20240208115813+01'00') + /Trapped /False + >> +endobj +2 0 obj + << + /Type /Catalog + /Pages 3 0 R + /ViewerPreferences 4 0 R + /OpenAction [5 0 R /Fit] + >> +endobj +4 0 obj + << + /FitWindow true + /CenterWindow false + >> +endobj +5 0 obj + << + /Parent 3 0 R + /Type /Page + /Contents 6 0 R + >> +endobj +6 0 obj + << + /Length 7 0 R + /Filter [/ASCII85Decode /FlateDecode] + >> +stream +GauF[afZr%OsN$$?ZCN;:U+hm2(CkA#-&YV>R3Uj"qa0Zrt!2qelkQ>N_hnSoNp?Fgi_i8SMXM?UQLkW +e+;HuHN!Fgq#t!&ci8Ckq"<6gqs44=YJ4\WB8(gBo-Zd&HGAJ&?[qt=s8;3_IbsZJ,1\ql0j-"j4!&gj+$$s5&'UKp.sCidLNY[7oB&2WpB]A_uDL$^\V;XRH0!YUA=Iu +%Z:8Umghk_1;<)ME\HfAn5&"L'8_D*5B/gc\%hpGs()lA%t"(7M#VbsVm$-fq+9l_qVVEb#n(&Q(kFT>n3tT5N]B +2'"Qe2]"sdc^+%2*)H38D+AqtIu!]8IcnkYjmKWEl*q2#K`?4E:[?L)Y4eFZSX9A"(i^"/Zu5d+ +[PqQ,X`i-s!Z)e[qHeEq +6Td_IHQP0B9:X(Op2k::Mnce\8%[bB(epHns2=+T45Pm3POJG\"T#$9=s"MICEALZf2kM0N'8MZRt_tF +^ApFhhMohoGKcgZoK`Z%H%1=Ai:#h"\A6u*ZT9$$3ut^UH3;daFNKp5AS`X'4T)KMi=4XYP;M[BBmHc& +d=>1.FaH9C,u/+oONh4^l[$; +nV5r*b6>+C@s4DSIDr^dmaW/@;N=Ul8::XNN]&WgN-=HOLO-:tec^:6A"_?n_+N'WOGa;@k,`91E`RLZ +LH[Ncfa0h,]#;S73Fb+=l&lpRhZ<+-]n[>'^jc+OILMp.dZ/h6pe`LWm]Ns6%O#6iZ^,9_>UMXUl`b/7 +qj02lQV#h^neSNDZTT#)Y4`idH[W!p*fR#4HEQV0V.DN`G`\!Z&OY2@ib(TAl^A8e>@%7HAN$?u6_Z!0 +NI@hB&&A[V&Q3PR?8%kr?)47'5tb4A\(,1'S"uiMO,\nTghqlEc,Zt#7Y2E$7bh>U];BmDADQX&^s0Ul +o0!&0[rLlQ&"f7ZI8Jh;FUsq&'%]s72l4MtZYWSB,55R?fam#iYE2"4+#l9/BiuOB@"n"(I7#AnF+oR) +gH!%p-$sF%Af6.R5!5=g2?#dFTDaL55<]%'Sc1i&I5lj$?#.dEc\H7idL7QA>J;0V6;u"eHaL3r +Hp>'rdsWJqT[>f/Z'sok6dDa'UGcP9A3PBZBNBA%j.NA8!2#\CDJ)0'i@t91'0"D$L8QG+dBc;8gDk'6 +^nibODG5ZkBL#1Pd:Q]?B$0Sm\hJ%[J]`45Fh*9AP?#%/)'R+jY=`!3jps7/>r.9!0.bHL_$RG[T)Teo +-TqD6Q$U^Em'l0XTLplu)8g9/ci:hJkq"$HU9i.DTio:PXJr221_O6?Oj +Q1iims/1WhLAd[Mo!6QIhO_KAr-84I]KQ9tDU73FKCB0UQ$%BO_XdUP]M!SM'=NOb^O<"cT"jr-K]fN[ +_P=F9hk'ji;]Djp81Dmb5s*X6Ue;'@s$:LUk>)e`s1o`Ik^G?Nrs'k&NthL$5BMIk0@/PP$NuB&UB-,4 +5Nriso-[i-q&;'Cji'?l".PjMiPi<+&]sW/32-$9r+uMYfCAcur^khfAM3>\om_]ra&pO8g8,$[`sh_o +o),=!i;#TBRaLE+I-VTXnoL;TmZQX3ITklOt:9c-bqEC;4;/a_KbHna/L.8k(L0Zp)?p+>-aY$bR4?ftA5>TDNO1ta/ +le9\"iosoqg##3n`-46f]=O$W)0/["1jKU1BS!Q72s$"+*tS@E"P3^pKb)GJ^&D/?ErNR0L>8qJ[lQj> +Hm_%(eb,TGSRYAA5O\!D"5W54I$NQc;8T8]m,4TC+WfJ(p/?/NGJ2j;_1XfaLgGr[#Y@A(_;K=Jq>8X3Kj1F,JH+R`m@d=0r`f`jaE2?-k"EKZto"Q[2?J^bVCnGu0*` +/!q?s%WWb;Sc5+;lr7E.>kW#&)nhagQTr0s?E;/<*e(e(Q-]%.qJ<\NmGTl`mI$KMGX;'tUQONGWu%52>/=1.MS^AbbE(t")'AHZG>-&_]ZSL-2(7hBi))Se>\E+:H%G\_k:Il'D57M(73B)+*D+p`p8 +4V7ho.eSEY47+36N;"tI#r90BC#+k6O!&6He!:Y50\dgYO4H6H@AP$'*/NH@?q(R]FE5N8Y"0Er&<=is +fIo$sYKqBIPgT4$r5.06lh$;`7UWp-Ds7jeTJRl!(\S,$@#lH**5YWkR'd&Kkk;gU1a)[*3u(\\?Eima +LaR_rjufaZCDL8-3=V2/KCMpD=L+!R?FWWsa&j3F#gMJ]q;@[PQfB10A= +/*aB4G92eWP`EE_[Z23@6fTr,^X/op*mD%:g>9DKLRr2ejP5K&f+kp(2n/]H2UAV_Gh@6M'o_!]W:Z`O +B:lSTCYi5c)2r_A!\MtcXg&q:gSma07p6V[^U_#-ID]L[&88p"&O,7FE6E1pN/s@d95]qM^*J'HnNd\* +I!HqhKbQS\\m:s)(R03k@lGT,& +NW-^Z!C$N&G4u'J!C'&u&A8@E80smc+qH"0N$>YY[UWfrd#h^_[U8Ql>mGW0^!L&qL7s[>l]Nps\,qCG +38V$Icnr.aB00qW_ZBT[etRJofeD$mr9AB:;a$j4A:MKtE\qO5ZD@J+clm3ZWC.+g$IX78jpNt)&_m!k +r&T)T%!WjKg6e@lngO,+W2PTuC#LrD& +ko31W6\4.!6+:u!1A3[)23(/.(o_rj3h5r)n3GQ+:lmiOl0B%mh,9HVK[n([N".+Xn%tbeq"uMjo?SAd +4/E[3@'5$()q_d7ENFs*oiMgpL@r2[`.k[_IHI9+LsnKAe@,(:@/CidQYc'J2a1j.d(WQ!>Pi9O+u[A! +Qq:[=MW)A*&E\j0T(Wo(^F<4%rge.3`1)*A=:oK>WDJTr<3?t@NHOpC3jcft/?X0^l9G'=H,u4#iba%= +Yp'[r'ldVg&T@%j6_C_,[b'bQ]DkA;[<_XE[Z>U6Li$rgilFTE*%PJc'9QP$.7ch-07uW>7Ju9ik>CUX +ECK4R+qp@DaACnk:o9X[]8U9B@^d:^a/PehQ5o@^+J,'Jtf?a1f( +pYTOmE(-75DLW[3D(#ojg#CB8kJ?oZM*HM>(oY+29jbdn;hZ\NKfo_UoRC>$i2I8aQdEb_/O#W+>3JHS6d\ +>7sC?dT25[!nZl3igEN?]f7GCHn,*E35UHq-mSc'(WBZ%s70Np +UV6%fi0aU&moB?lda.(QcNTBZ_\7T1"N4Njb$+L`DqHLfPu`i,U3+V8i^%aZg$/+8(.j\h110o9p2%g5 +Il5%uB9.kC^Vh*dQ9Xc_`eqM9kH.)toLK\/l0B$j$dtdUJ45P[6dKSO"hTKp^tS9R'`iRKid0SJeP92q +@TsiN[^Y6-d=PNYSiR.]7'?9f`(LkG[*lL_P +N,K0m:8SCWqm$Y:>RLnJ-!\+oi,ln<@bf,S]8@53'c+5Pr7$^=D[:Yp'/YhTRZ% +hD7Wt9X@p+_3=@>CeTf0fs=DT`hBF`2h>HWf[4*m:em(tfi28`+oo%b"M.b>^imf_^Q#G+]X\15'l,:[ +!!mAZ^Ca9;`'FDfru4uA@)GcJ"Q2SiNA-6+X?V:\HYZEu(*4nf,-ScSe$:/o[WdL?Coc$Si=gC +qm-g4^Z_paJnNI%6.C%.4T_9`_Z&f5M?)k@L]FADd(\eKFL+G(h7R5<@hA^h+X-o^&gIB<4>#UOf6l6[ +HETY>s#SfagHc]aM`YZ\Yu5ccP2q%O*"_T/*^^V[/*>`9@6&o%4WN`7hkS:^$,o^keUnHZ8u0=6j@0jI&00LuTX?%j(;c*%cGJJYKotm[;$IiU63[4X]nSFALV"Yr0_H5]'WCN-NHq?D4 +kLL*#aF@on0e^6]ht)6G[Y.D:L^o1?F#1-Sg8IpmU(J`2+u +U8KeuG[:RO=Rp[+:iR2@^k8G:g_4pY]"duR[8?\H?[7',HNB.r4<6ppSk^DS!lAS4)7/g`A`r(IT9u4# +A,'H>ibPoJm.Fra*3WlHb004<&%boc_2]@"2skKe5Q4C2-efL7@fBcZB_M\MCOS"ue`I9Sg`ZPpNKIKda:8TVl#+5fp]\QeI'!\_+,#ngg,E<9'[AV*n1pYo_ta%Kac0RA3=.j +M>=%>qG%WH4FPq@698jOR\0S_>Lq!3>9?Je,O5lbqCV$p-0ljf]cG$>A71HblBh'U9#s'WnpIhbIgFO? +cd[&Y-c\-Kf&3J5WmDuh(C^u*$P)\TjI:Y?;2+_fUQC$i$5m3f5nl]Ug.PJM+q!Q_FF&lg1gAYjla2sP +8XpOf+6rAb)37*Fh9_q6fnlZfO,s;?oF\JAXk5hE@f+N0m6`D4QW@oUXk5hE@XDh.psQmGlpIMm^h=?<.Rol+q7+H'BXj6"YsrVhdfl2>39o!#'=2BC!PREd)rFc&Gn5c03/Tp^BQs'`S%&Pd +lGM0`a"a3aC969cQoPqmIOiCq'lNF-g$3OC9`9EF7XB:4<6dE6OS(%:5k/W%5fC3>*&R??#0IsW4u +km\]dnDLJo7iXR.lp'L6$,EhQ@t2P@\*%$gr!6&cM=tGc2,:kK +kct4RU*%E&&;L^^+#_"0!fp%mnn\3[A(-pE9c-M8#No4B0t.HSa!M@in^"\(,S'\@q+htgiLUS4KXm/' +rrkN\2]_Gc)i1D[80u5nS6P.hmnTN!jNl+Ql]ekg>VoqJc=[AF>YB#iP`IX5c03&iqd$PArCZ"+_oCI" ++qDB2%aH'/b76cX^[(-,\c"/8Ji\A4>drTZg4\?@?VuKUF[f(j4G?]*/9=SP=3O4S>)2]LK3$V%@7F=1 +9Q"8j5o_+Ujh(Nn0@SYlhO(9BW5m`^/?L+1Q'NUWY+&Lhe@8La9e/1egD(IoekT@j9="h6P87sDb.4@" +,R`Bp.e5mK,fZIIhs!"i%iG@2*.d:&_oXfdIcB+D:QH2Q#em(S*ET-[i4=\R.\88#,EDH!UFW[qWDftN +_HpdqJ#5BiWcVfe"^eBA#'iK)28@MDX.=CtY7D&5f](CNhL6L3],NtcTiX?']&eeFWlU2g5jH2YHV!H# +fmZG5*u$^hrbT2JUKb>>DOl"MNpIm<[P7^HF1r%6n?sbj'[]&&"^Sj]Z08B9Ph']pA&-`c\8Xic:IJd; +#:lSPoB&rt!?M[6E,dQ[a:2P*G:%U8`*#4BV[L-\^8\o[fRo\klUC8F^lRh*\S1^N/`g(f%buag(#O/e +iirPX^,+g$c$PrpUY5qnH7-_5II2r"R_Grp?CTuL\RB@dB/q^LJj2RPP'b\>.*6`&TUookUA)Hs-?1Rh +Z?buLb=#*n.h[(J_U8cO[6J,'<^$J>j`qEdo.W#=o.[O)cQdMG$_E-ILs/"1]\AHZRoTRgl;qXL4b%E2 +g<@<:_Xkht;'3^Ia=29k10R=q*^nt4#`#=_'e=Uj6bi8!rda*U]]S6%AnY"q@Aee))s/Y[+tPf%$p0`Z +"%559e)K"fVfL4s`p?Z"o#M0c]^/VCl.E*C8b\[<)sWc\b.5kSREit1\Ug:aP+<5Gn`9Q/5i=H)ggBor +Z;]>@*HoS%$ThoJ?$8hMJt4Z=eqZ0_HO%Q(eZRKF?KD?T00<`d2Sr4/#&0uAo1PM,hm%8&lN;be8q)&\ +L>sYBq*-$LGA^n&lZp=Xu=$6<5)U]MV%/D'pTIPk^]Rn_J]8f:9%2 +mij<$e8Pk8eBeVBe9ZOiUDafY;&f%^A;`@o]D:;6#ti&R'p[m?)K)762'_T[2.,oD?h9$jXblQZm$.il +D^:\CSc=5F=(2I$Tfmu#/UaHgWkIT?PN2Na`EQ=gX`T`rI +#U8HZT++#OUW'f`f&4L!.hQ?s=(6tGkNaWX>'hR!ro6bpJ+!S/-Wt_rra(&+@CD"BB!_E4QKEBM>kid) +D\92bs*F\(a4Yq?`S9L1EM$.O?R:%5eaPD(^9A9Zj=KXHdMI(LJ"EimZbZ82qtmnfbMAAFrQr]jK-u"V +pQq`6EUneBTCMhtfQAt=A*+3S>q+T*8(uE*pOYP,Ar*os-TI +.t1!KIC%qIZXqTilk$5R&@KlrE"<\GD?;$e7J4jjO^>`qnI9^f(VZ@:/?=)]4c<)6"iM&Xj$9%g>'.%'%lX>=3JGZWX;)SrV0QetQfrUdUZIGo@NZ:,)VS]0:!but:,,A:9eZSUo]XVRpr +?P[\bY4qe+RdjDK"FENN'^(;MS:H'VrFu>G2_ugg?d4&ALjJ\i-E$&\&B8=W;(G,9?\/dN]qCP&$4CoJ&@EeC][1?L>NarR2LJ.k)gNcB'#,Bd3*:fMW+B07qRM=@n,dgm/Y7e +.J8,2N&^o%AB)LY4(LfO1It3-i@cW9HuI(7^Ijo&O!kb0Do`>WUK3><1.+*Ub`GG]),cPOo9q>Vi.OR] +bQolXkd=H10@H'pDiXq!K(G*K-`MUuHt6hgbh^VOb!*QkOM,nBD[OHbaV4"Q;,Ec-!f-?5jBfPZGai%d +kHd[C$MHDhL8.Tr7]KgI%d1NuP.h81W^f!rJ+-LJD)CoISUUAt5u+o5)^C3W;XsQYXQTWG[g+q,>`+"+ +%70d,d(8B`q,htoPs[9?M9B;2kLCP,OA4@[:[9:g?i8`^c^=q29=t-4Y@f* +EF.AUR`Tbs;bMiDF_&f6fL*)nNkW9[mX3-$O8/.ZcHi)&]bYb@o"2_k`-9/QpR(TrSC(]V2uƪ#>; +lB1=^*W6/YfQ'0X(oa2IFElYpS$tqblj&P>_-Cqh%Hs8hDiGC\%-_KPjRtMiE5]\=^k$d8:Mru+Q3]jW +L+[fKhqP!,T$`h(eW6t,a#u7p$)>=R>2,pjl"%8;q.W[#U#15%'_E/IIKL+1C$YbLpQ>V>k>C)8FaBCL +lW;%YAI300la/S&Ru[5$fnH/iQ"X)GDIK9;jnC^ir2j1_#5kIZ5-j!L["RhD,56o&ceX5DC.V[gM9L_Q +97FL)Tp6,Y"2&lEfP],AIbrOe>'X`r3+V6uX9oEHdCP?F@/UHT!k0)5E`rimL`]X)4.IcX+Pp>icdi?5 +")^'M1>M#;:r82d^nATk%m&[(Z&Vu>7ZCc+6XT);T=Eg&-0l#R`e)sCC'f6srB?3N/U)aS_3X*)Nk!\9 ++l0g0cmuTCgDfdZbkV-'p0QORM7^-bf8$hIcH80rA+r#q&IfiG=RlHO1!`ShXSX"Z-o:>jFTYjZQ/4O8N8m!D#OD"i_EehM4$:4?C&:rg77#qKat#TK3tb>;4Yc?QQ8 +^o(P&^j&&Ihht*CrSW!4XY8OJAuJ">/9tQFVrD%A>O@&jI!E*5kV6A8rJ'G0kkS"ZGi/725&ehNe%4=_ +.DH[7h(o+[7Z-@nnaWI80D)+#NV&23dk\u8T/_3I]8 +;$fAu"`O7sDQt@7chHCO6dA:+LOEQW^;$qDTXV]nGen8O-k5&T[QjK'T1tCaj0;Klr[.'jRR4M_/#Ujb +'cF=3e-c,-1jKS8,g>\p9kD\\n6c?8git@ij2jqXp^;iuddKE*?XU[]]GNZFbu#@nT'1<0N%fPc90rLm58m;h_kY]#`G.!=U+$8R5.,> +Oi[=Z7Z@nj[jKYs^fN%%1n[@hpW1nBWa"aK)RX%MG3UCZ*GX)C!L9\R0oLXKQ#8kER^gWVf$1\K[pr$Q +?*"=E?"eqL3bDHniWM@N_OY!m&S)YW_ngL;O&-c0@16[X,5D9lHRZ[omMiVIE)O&Up,0,?Op'XE,Y_F`7iPV +)`MV5(P1uTp<"/ma&@LlGI1<_`O(q:8r2aOk5F$5i]_&',8]2X1#XdFVMJ?D:K2V?N7V694p,u/[Ikq. +Z5\DK?Q_b&;`h*%1Wa##r;ciR`5lu>G7*?T::KW_(Q/2)q`,GjdRLh.]qof$q:3nj)[8G<"`O7O..5sB +0E60u_Ytk.hsLsBId)"Qg+,3@s,omirLt4rQ1&u0`<_8YT#E?u_R"K*ojn@WP?e6;cNZP,FGSq>SS(,a +3NY`5e58fU/F7X8AVjcJ:Tb`N7=U/LSonc+8FbP(LE[XL<3`\LM1R[7'k)!IY>H0G[WSI\NA:"gaL%;1 +d/Yo,]$\Y;q=YX.^GHV6JmYhF3l,9c\3!l=qgL(`Y-5mJJR+GT\JHZYn(9Sg#gIl0rFeD:as;0Fj@,9<:(FY(_;W0 +r.\^/_AF@e5A5Ff(o:Nu)]a!QnVn%#jTq<%$YOk>_bt9o:r1H'bkLl>\88+oiY]Ym,'GL?o',nm_f^N*_>r&G"Pl+ffMe`$H+l^l-2*)6I%X3l,eX`YsquONGBBNjd4'kWo +6;%.id9GIVYj0;[2pi8=N]?a5Y7Sr;0)WXR!C$N&m`:L\.N4[GYK,TO7220N;c.(CdD..c2nV&-H)4/c +&]a9?.q29G]U">kC$U8ANWJ4Wr"$fG$`]*j8_48egj5#gn#a5e:1#jfbK,,BmE>K`DWYWbb)o^m +9M#J9%q=FhP+A&d?_Us$U5SL9nek\]Wu":qlemWskR7$hhiVDs>[*Em($RXkoNBla8.qm68CMeOo;qK* +8W0J?:;8qp?PQA07m`r[n4$t+r3CXq>OS]b[eSD4UboWZ.$u-P67UWO`@?,>?T` +aN(45=an2Eq?8Z;ZX)Y&e9-lL.h'a?LZWG8hA`%(^Ilh24V@p:qS"@1cYOi$LXNqE50#9a.CK3&B)!kq +Yn5VNTbmh#f!B4JO2UbsJ*iSP`?%VIDe[8YoR9skk`9('m$Ad-`>X>8>obs=4VA)3+i\3j99,8*%6F!Z +U_8#"rHZld#HLh2,u<]*?s,sWntu+BQ7!4\0sm0RcZ!N*b4p-]>mF`hdM)+`F8.X7R1@R*LIYqAnH?;X +XY!=V0A/D=M!^\>noV;F(LlN`j9ZBQjklS^%ifaf^]27C"SS&pT'0h+Qn$J+md9LSc0jtG/o:HfSsf+` +*;-ZS8c3gL[[q9AEENe_EIM'W%nBWHPp&Zo6]kqS>^[ZKm*2q31Thuco1M!X@3b*_E +r=+heeLga+Z&opXam`''(#uD6YupkSRF/!=+JHNg?t_okjloXg[O"G"l8JF?]E+U"qrPHh-H7V3*QTo% +,Ks;VhKD/i.pYcRTe_Y0gK7P8N=@_e]%:\18(Ki;?e*2Vbq#RQ]$THMT>C\N0bhr9Vua0SnTaE$>glf. +c`"U2B<^'83/Z+/[?cVW+neN'`Ej'h=Lo^:M_[K2hYa.i3*/bdZar`IlG3-&\-d9i=>/l6N1bEsI^GjM +?,iF7YoXT]:%0+`=JR_X]VUSeYX'=UX4n%q8H[X<",t( +NX;s[=:n4+%Om3+Ve0Uq0&1$=%@WFX!'^?BSB9prYA7aP ++-g";nbA)%m*V)l=Konq)=l0la+t#]_m>S;Nk^JkhcTO"o:J!8K'rGRRC$aC\Gl05P_D73rmRnp9^%*i +r6G>bokF,7!?3eKrN/+g't\31Ufd.hSUitX;"nD+e(Ppq?:Ds#([Qr>U:LB="'/N;oS(ISK=d0LGFV0QsPPUBNZ>->%!<)"Z2NYCJ-MR-_o'VKf^'dmF5,3/g0hR;?='H#-m-Y.oJb=DY+c7kZo1?j9Q/I][ZsD$1sUH+U8E)MHHfPP +'ig(2>"PF=&t%PQ^\l?5HOcPTN2@E=+7a/*e#S7Ab.Rb@?Z11tdlQDEG[@@G0d\%=,;>52bSMfGT*1R`:">^A[Tjs-17rlb>AO'@Gt1DUU8WnK0b/ +Ic(?+:@k+g^7Rn2FE;orDDm"?'5!S];&e&7Jb3m!5u$+jfX-:-QK.f+IeU[?KCcaBlFl]cI:Z8or+0GO +;&cs5I=-a[@'r(:9QhR"4Xd41=Hu$[W]Fd@crs8tYeUoGWf(c-1EOLjF1AZ]IPhjiA +b\14uTVQq-U?k*R<"[Y6&_6#jLM,rsIV3$,]m&bh(s8%+#SCA^NES&7gu0A:$nnT;=A2&^kAGp(-kd3b +D-660p+:L:)rG3:Yg<&/7*_hJ'\oQYH<8-+4grnqR)feT^5E&GZ't]qf'IcsVgC]GZeO,I5n(,.4:-;^ +[be7;\/,dkKoolI?b07bHYldskD%bu&S&6jF^OsD^O:tl?GAR*rJGjsAOD(d\+c#[O +miSVhCf[igkk!EB)kN['P6EU?jKN7cU=C/OSH)$>d9OfRLfTs&J^X'.egZ:I.=8?tak%id;\qTtH:h*i +-Prn57"4i^FpXsKXY/u140NC.o8sk'h2\5HZ0MdYW$m*UE6;^$jZ"G^M:(6.4ChGF86TI\0DM1A=X7GF +'ThF`<_/oclc#7ogUcYT2.^P9G@X8AL6P=HW'A(q/MY\B+WUq&>k<]ke(\g'59.EM&QEOtAt7f'/\S`\ +1MjVP\:qnrS-s?qOBZ#",a*H*ORD-+@S]e?*AQ>AS\g18-#9b]"o?k%5C8N8knNet)@'9"UD5-k7@/U5 +Fu))o>rnuR=5V1hD:1];B&ZtQN+Ykj7Rd#01,VPOZgc=27G[#+X]LeJh!o4/rW"gnR`qVbi/+]L?2Q[I +kI(I=jfr<\&F<1_)u=n6XBL +khWp_EG1;b?&;e#5i[)tiir8ce+L$CJ[]U;[m.*u\4=Zmmo[oVpHES!IBNY+0[K0*V@?8XfX!2]"qZ'1 +RG5n0\AOB<-tYQp*PjW!VTd?p5%WlSm9bmVYB7oViNom_WHkk;P0V:t?A/sXc%3P0/M-6XUiKBT,?#>oBXf3!`KEh$,/ +*&5X!Y]m?[%t2o9,<=UW;4eIP\F3sFO%KmH>iE"QKJ:u&>&Bl6hKm)BLYJr`]-u+&Pr\I5;"Wm[`807+ +Z!X9;R'6g_OY9BXgY%XHr#je4BdePpbh\nq:[X/\We]_^JhJr*)4;mfV=2WUF]T(P9upu!$oR+L2gR%: +TL+JpfOg2Tm^R2ecic9O^2Mm0D>_lkO9!7&qA)>#!>*2qm5]`!DPVMTFEF@#W-WhV$6J-<(k2_3fMEi0Q,]1&(Ac[-TnWY+DDn4h?8 +an+bQgA;U/m\csjT_kAjoA)=d=OXmh7d!LSX(;<*A=Rq@sAqTE<2K-P.&gN,V +MYbKLG9ASq.Bj6iWq,F+[N`j'thmH;lO3V`-#8%<&Q) +n\C_]7LnbR,GLE^"as@`a%iJ,rpN)hCVte>dgD\/V:&p11p*l?=5W +/)+Kfhm%#R#Nc=hY?PBn-2G)VY?PBn-2FNFgu2oo*,m+Bl\UjESCT,q&&E.p,%Br%H!:/I0L&3A[iCk- +_l7b/?5_W_B50@YRTd\p`-'E0*sM)61$$)CQ'GJL]ucTuXM'57rkg7mG`Pa7n%HJmq=-Y;EjaVl:kf;h +I`]2\3p-nRh)!`.4[X_h+tX=pX)i(H-[NYC5t1OcHB/KH'lo51;u\6@AU^4)LFlu"an +;#Jc*`ZCDKi96"gm(<;!2hUY4KDd<>Fq;Ei@6!pDEMC\b4@$[483ak/\lJHn+uh@';@G +YMKn?Ws^aBZ9tE(&LWSp6ShH+'PqaZsoAgj*InYBZ9u!MZ'@dgP8gG +Mf_9cVY-L?t%D&0b.?\Q_GEZ1\IeQMIVhggHZiBXsE=>3\KTcuOQJ[5d['CAgNCoa`W5&kAId.S=BbnY,'a9?Rch +e)WQJk2/9m>,eo%,ITu$L,afqo(2d:).u8FjD^q\i_!b7Q17GKo?C,-PHd+W*n![bB=)6esI>'Qm=$2s0L,NmSp6mt!eedn_..sT_ +[AXa8lcO^F#%SM$,.,E#$-r +cbK`<sL-d!6RKE[pc2=fJq)VMRl^90?aR]k;Y?F]B/>,O/'iRLN:`i_cMjE6uK@Z='o^r?5J +Djp"*juK]]K7)EVSY_oX0`$.IaD8Oo2qPaA#ElUVlE%sea[%QTTO:Nn_uokuKU^Wr(Yms]:DZtWj-pD@ +6gd?VT]NW,BQ/>dT.Y%qX`k1eNE[Hi4L2eL0,WGome5?oXs\UuKf!mYK':Rn:p3l"fg-$XQ$@6C^Y\U2;;AS20DtZk,l//GTV6d:7TA8a*BLo:1IN`dTeh9EYFZIt7X4iYDla13)/>]? +Or[F_A7rYfLGPo:asNscDG[DjG.W&gFE'j`7`/SRUjVY$&BK.((?gnI_+e:l1nQRLHD>XL%_mF@Z1`r9 +^Ch+UYg/+FQ*!fj/AKKn.^q3TrbT>^13_HVC:Es#TliBQ4/aT_5S;"l)V +qX%T(Jpm8#.=ZQR<\6>@'D:kB/g8Xe?`cbtr!J)hL_f""?<#H#30d#h&E7IfM&c9,fD$%gg8t1WcM5h" +Y;j7l'rm>@NhN!UUa9<%nTk*.e#F;Vn_&6Y*hWBQ`ojI]C7o;N:lI'@@oub>W;_gppXejuYuX*_D9PA9 +kSZ@'&CHOgpR&2]6$8`nCY%J,McOTKlilNFHAPW:ZIW9Y:5up`Qb<8n4d`*+q6,F+H+H4;o47l]%gDJ# +Dci91F3toBF^:+tUIp4cRM71od0$d2:)!aE+"iG8QUI16Q":2hZLpFYRH-b*:oAtjK*D\=%%LI/#JYrj +dsH.J1lYk]S]0k+[4hCr\s]=Mek.s>H^tZ"YGM3fQ`--s[oF-\%F";:iX@Fq6fo0hGJ?-KMNsfaP5]UZfbTs(#>ad^W1B7^1=fe8&+Dr +\OAcg$rmEIaRIRuLRIR?Mbh/\`i'lN>`TrtfWfWgB*=DK00NO"B86.%ri3GW`?%UbCON="Cd'K-@-=Di?`(`=5?-Mg^0:6dUU&eU +-(aYn\ji.6c4IOc?<"M2D(ka;ib_SO@(1pd=N8qVCVK<."I`@6()Jk3IGe/)Fj;mgHZBKia%"H_Skf1P +FBW?$Dgc>n-7qV)d5(YNQg0mE9>(iC:B:0KVs_$,;"r`8\,>q.Lr0m^?)b2+cO^==oWii2AbXp%m^763 +IXZgMq.^@7f&j=Kg1&d62C)cr@`a1&>Iru61YsDcf^1[9]/uEXoRj!2/Cn_FCN6O_ocW`Xq&f-Pme12Z +Q;IT(c@<3"&&%A4>u@a31_e:*B,);(IFMi#^#!55V"_o:J[O7-Vm5!O2jN!=[+h?^@(.LnT0guMrmtqe +j(ciEm>aA@]tIsiD<=<`K4;;[(qVs/V0n^a=f9kukLntU[LB0$'2r[j`?7FB +8bq*#TX3B_^W(!pEUSOnG%OgAO]U#tMHK>?398jr#JD.K*[:s8f#q3SMq?sT=cr5$b.nKe[_cL!/\+-I +M7]M^W3nQJ[,Ul-MW7&SNXr6O?&h3^iqUlXj/!L29.Q#5XZ0WjEP/[WQW>(ZXZ/MOico1Vn^<sAm3eF\Zi%RrRj)aI298uF;9I;;=E,=g;&q9I:4o*=G7Z]5mKomTGIYm0 +qReCO^<=>jL+%3[o"pi->J@-_XOo)qN[Uq@\$5&p4/-l$GV=GX`[Y#`%JK)$;gZodke-:47Mi1*HOBXC +o[U)A%j!BAQ>L!SYO^EQl-cu&g>F[\'Xk>V#d*.2#)X+Vreq-TTYFNtF1p2#F.`,XNuV'X2/cREcGmN] +_TKbH;7:O0-m8Y2iQ=)bnVa573jf%bHUIO%jm0E."MN9M^GHb!:#M?ul&VndF@cipME-o0>XVNW0A?C4 +.@_`]8iCYLMuFk=K6!2<&7Sf7JLCs:Q@<01A09(>-?+'C>tM0iaF2O;HmpkFO@r@ZeP![T^&&N;DV+gn +O#Caeb8L%!&BF_UI/XfZJ%AF,(FJYJKH,1Or:07Uq*/;YWr*ZjpY'Z\5VH$mQ3'pnlf.W0/Vt0&bpW[lHh5_+XB00geKT:-4J^\b?d;TquR +,-C.\>"PbpJ09]6FKHP_nulL,7?))3Ipg:.c[qcKqXoEU',ga"gp%P')YgJkn$q;)YRcK.Eh""#Q#3&],&-QbNu@U.^ZQCh?LakL)p0i#opE&B&cDt$ +#9Orqf.lKUoP`mukH1lRb!]q6$8dJ7=j7(Q2u1[lK;HAto,MPSqp]#Wbr[ie.q#oHIP2Z:!;f&EXA;(\ +MPpEUT6SiSLkNL[qb!S!PI0(71OK-hCNHSD(:QYnpdtdCm=5H0pSjjIrmacej?4]eiauXa805N6CtW`! +KiG:kKD]?/5el:FigFp#a&YuO:!t1*#[^.V)WElO35glk^\NX)Q2$]1_,6%6BGL!U]A3,U/rn+m;Qm%B +4'Efjko'Ru[/9XleN3BHFuV5:I`7rg,3s]-,C5Th/e6KHYPuELqPg9j'=89nImtebKoag#o:PgXogJ-G +T63n$5*&o`M-M\2;n*QN4TC8uq1%Thk9&QiIs7H9F(m5Jk>'PeK(rtdo-O6m)pUeFDJ2Bd6:]d-6b[QJ +pjh>bc^O9:\4"0Z5'[da(*_n+BtuphJ"O?M92R.Ou8/N2KfXo/E1BFY.RMWM=&`_nP30 +=FH7UqO"$"c*?G.qFRuY-Y\/%8^lAVgXS@`=oQjP\@g_bqoJ;-b`I-=<%7^Jq;Wndo:$[OWVI8g8*7Rg +J7!P@ei(j\JFYZ;P5*cOB7rO@c8.fRb;uT[-C;NPW;:'l2DF!G'>Hd2dT7u?r43TVo +2s8>!Nq]60IiGM=EY,oX]Eca.#pmW`BC5S*f'@aX1VuI]d$_6D>3/*\hB9`m75i2WB=`sFnFr_0/Fo'e +-VG,e`eP.1frTO\JT8B4rM"q>DB/%m@L'$,=)W<3q)n23JDF&`fJBNhUc.69),\7F3>_C*B)FE$j@nUI +(.jHt6!9_fRV)cgn!W3_Hp;a+XPS$B?c3rUm@*'(WNSKPbs,[CL;?a+cN^4m`duD@M*7V=^C88%Er=-? +2(HmQONQ,I6t/V8G=XQ#Ndi)iF,od>igU1#cc,\sVeq99=.j&B[aSX&R'Y(Z>kB(q>1*.n/A?E$A4R=' +B-ghse]bR11Z&Z!jOl!(C1f&CjI-9$o<,k:H_*-ER<-$MK+!I+"]tQ":#D.m3O4f`Nd-&h&3lAA=;$t9+eHR(]$<3K04NcQ(f0b9!8l9\effsY@]hVjF[;'AgWf_QAKU5?H67DnF9*KGY&c.iMbZWW +da2WaW9J+ji65i#cctHp,tQX5(7#;?,8[!F',f`s>a>%IUam8G17Wi=_M!$iBcl6)G@#$Y.62AhMJ&Go ++\M<7J9@U2U4/3!%CBB[&GqY2/Y9tND@\'hO,\;/U%d(Ea\J2XYF(e2mtb3U8U"HilPH(?R#iSqH4O=E +j&Z29Z0F3"g%=m_ZZ5+f6aOlbiV>Ica39`j>KEEW[&%FVLYj.0.>:msVC<$uYn_]&$,36"nD)qG+(Nj% +V[(N[L6\q)4!Ak_)MrJpTtMk\m!hRuCe)>_5qZf?Vt@75GtRjA39aPX%kUO7K$23aZf#(Q]?ajTr4MJG +[-NZ]Ps<9PGHg+pRskph2Qg(O4''%/9&$3Z%=*j@3(]TSl-:`SdY:s"jqGO1#S[-2uVKh5pdm;)K +f*JbK24Ul$7Z63uhp3FN`tr<3H[q_ioH*Ph.n62Z?N#XZ[`a:$f+h>32>5`eL8B++'jd0=Uu/p:qh7sf +huoSiqj>,uoINeH'n,a@=YnB&E1'[JcZEaP5IUtf(%jioLYoAbgCGH./5OTA@`A$LK6LS'IF#s\i!DMd +d^[>^Jl_\d*GH0L8_T`d2d/I4=*umsN$.b3iOMR.7AgNsq26-X)PPJjB2:?nXeus)Ama3)[IV`:l\!'[ +V8CjYI\'JNQei0F4hL#u3$5iGX4D5'B\n&Z2sEt"NRbNkbrcRRHIe_Ue?im0eBtFCpY\Z3H?W0=H.TZT +b0F(]H0\bqd(L`h;1X*kkZqZ_h(;d" +mCYC=QErlj]A(Tj]-"trV5na#Y?^O6q7Pr\6gEL0'j_mc?$_ho%D>D.]t:+D?172IM5K,U`Mn'*V]JI^ +#X\"J7_]tGTaTW6`6c,#)UA".H'ioE..lr`J*\2RatH%QF-?5JIWe?Pp(K3\ZBptla6Mcaj`Jb7UNt+V +iI&%FNkQ.V9CLl9VY%$b'm`qPH<3)5^lB/H$VQEAq+iQTCOJdJGL\M5>sn53]/XXW]kaPOf82EF8^Zt5 +Q9V(9CCRtX)+cOfrR/<]q>1CeH^X]75;Gb&4*0IN;"=H2roZ[rs5AD'4'=02(%'7E.t)!"."WZ`EL7[M +=!D;L2gdclkh7!5=Y3h1G`<6mbShSIC2#`f[+(_6J21RPi1\]RqrCm_NDVLX]S$6GQEnQiCIDt#=%ZPk +@nU$OO\<"Bq;No];s-HJ3>&d\r$$WIGU_O>,?LJn&G+W>rP5#1^Ti[YBVMmTCF_I,Y+3D+Q2E%;U0qTi +.I##;ZidYS7m&r%rMo\eI*nbr_WhrNo3a5?/Fb^uQgN&i:t;$!4!PPsO*+fIjq-(:"h*,Hd6L+#E-/Xu3XICZ/M"k`AiX[kf4/CX>-pADH&>NI:8=`SQ%IN`^/TZ4k+G +f:D)KAuk7_/Si:2mikuLdE6UW4@kUZK.V8i?SZfJpI=M8?^6#37uZ90^Ca+dNK5j/hHG]L#d)"R,Bh7Z +0m9$pq'1&uGXUoLd#-I-d5Ad5RqQe-r\>lLs+7\Je3NA$<(?4T1SWO(Ak]I6iB)+`r/T6s2qG>@JW(1M +`GUeEVV&$.*ttp6!\55^7ZNX@[sei^6tZlYHc0h#VNIo:;Nd.Ydk&8@T&9-[[3ik@1(^sM)>&:!"*=k)[&e0>p,ZC1T@KMR@^gV5Np:e"CC^qceK3S)\`,eh +q2-4KB8$5MeZmNPX&ZF'4b=1hFt:-HG)MkP`GUAD]0/.*i,?VQ295B9(;>:CLYe;aNJ4^-ZKM`=:juhN +XCE?`+Ef7B.s>]qS2`fSXod;Ua,T"IGR'@?m)+nWBL(S,>bR0p3>Wg1Cre>#udGI3a6U4tN@L.G;_:OMe#Y2lIT4Z)@Ni3`.\hD/mL1858:7!'_2pT)^HG/BFHQA3TWNgI*'bg+rV'OC1 +HUJPc9>o%Vi\-_)PdK"CG43*A;,NrG8SK9bZ*i&L1KSLdZ';YB9gM/1mCp>e6^Y-#o+*i2Es0]hb*'G= +c^1$(PdNP``_r*5m28PWSZ"i5+>T82@a$[R1KnBAOV8sL.4GT*q\IT?Hr+?)h>M!Km\0oabhQ37)qh'6 +[p.fR'n9dijA`LpU%NZ,--m5\pjnC^I^P4--[+(<^B82"Q;GK3<'#O4NsrKfG?_s +R9eJVmIX)?\3lcCmP-.(G:;H3^OeA!-g/aZUuXh#j9Am-bM?jNHSGauE=7g,R_P6;LfXOBVJ3e8>a.ge +L_XK%H[A1e8h"ZcQZpsAot@!?'OA3)%=BoupE-Up7CAV]9[S=Th4i^VAW$2V=j'!Tp'5U@:Lk90MkP?q +emBe'F+/aJ;>HBmHYa3,7U:?@4bhQ??odu/r.;fj%nHh1$DMU#Gp&t_kFEV+-C +g5h7fd=(Y)\MPo07PDGZ(,_O97JG3AjM[62.LW(Hd=(Y)E;7NhNW)jGUcU$%#@JPdHFG@6E\^_n+)km*56$I,n+t9fTm*P\"^LNI/l!>Z +R&G50U1`DqEHmSP]!O4AGu26JDAB@ehQ>N'eJtr#n)![1ccO\=+5*mkSIK?PjKIq%:L*pVRC`F.^AXTr +?!DC"G-W)N5JE[>8)PE?o;=fm5?W\"J+nN?oDIGm^9\CL]MVVoQFJGgMd,3.%>4D[UHaakP/EE"^b>&& +MVJ-tbrbJiM>Z%KYienB]ZJR\-l2+dpkcB'rO.G:Obhg#.@)B@fWBVE>Z\SIa0#(1C.IWV4mLf17=TYp +5[cLsl6G[ZE_;*3jX+H&&A'4l47@YHI9U5sA0Y5HDhiHBT5dEsIcMh)AOJXOEk?Qs[:pU8/d`E1fO48>/7jkVH`gEH_,UPW"nBj7Y] +!5;["n*L=\V>UE'qE\<'.F6UI+3Slh<.Hf-oe!5!BSc=srkpNV0agiu#X`?%62m@:FkT`;>+Weh`3]`R1bFJb=l&/^7]SYo(jX!Wb@JI\k&aC(L<8Hg%_X\.ROH( +0#G]?`%RBsl/sYqagq$WF^7"ocpl0g/8S81AL;mTk;#n5N.'p,S4h9]E\=t.dE\9*^8^(44",,%JK&Y_ +].?I0b\r\"j]j.t!p!V_M(RtV!Gcgu0$CA:L3-&!jSn4F8ulKCBuO09f3?!dj7kXZmU#ZAi%3+-B")CZ +#aC^=3P:n\-1[e$`oWjQ7mc#/:)5\pLQFY\,orEH$0M'Fb`p_C6&k?+('?Od +kB_rY^VmdsR_LC5LVWWg*MtYrAaP:o;=L=KMrHeVNBC>&p_(oXpmjtTCZZ*BBglWAJl@rH3F=!2B&s^* +ZK%g.^@tG9?WE,"\udjeHZU(jZW`^.JH!Mmo'2DHQQ.I3S$/@NFK!,!Ob,N? +R0D +G2J)oCPj/O&,`J(*1ltja7[H`73VIi;sjn9dkfdRJG`ZEs/@a3=ln.>C$jtIe.ubo<@(oi +WP4`q>VBhso,Dtikp9gUB%CN@J"<[an4&dtkpQXbqipR&W<\PUgF;U4PjQs0b+ihM/[K9RX3hEhM"rr*c7b*U-..je^c47_`'b^Tp:r/NDCU4V+g6!HDWgY->=D;':oB0)S$6dZ(5aSUQoYp[JpO: +>q*=c5lr[i*8i?iUV5fN=fe%;GK`'ek.O9!bG/mtZ,HFNB&?A5Zh2t\4B8#1rR0oBk9b3\f7(-A/EU,P +j(Y\C)sNW3es'7!%LRVTb^),DAOdbn-1*t4@thm4%?Sa[ZG.d1p15s=;J"N.9!`7hA9i@B;M>Q_XDe7n +0rghAB3K5"X"K.>9@om-*Nloc?AiS#<\:kh`nJJiE3.Z+EP:_bqQN2"OD:^u1MH=7P9W-\*jk^UIDmjB +/S':^TCoKSm#ef(+2kGGdn4p6BJ.^VR:a.rSR>Ym_8Jq](On6a(@uqE[Y:!Eh1!8gPK;LE7a9/JV57cV +ZW992g[9iPR#?B6eDqT[Am`$*UVsXagD8s)jq35a-`_37BfrY?W,bSUo%)Ip7t\fFeI*E0nPUu/ShDgDZ6p^:-aialB:n)Zdl*>nbR`9a\Z9(q"$S&Yb]6sar?7D,;P(JC[*EI[i8me9"SfIJ7Q?hA\M0782/ +Z#6bHf3C!.3dBkA4_j#kYgI.D/9o'grRP@HkUgR^i>2.,)[VtjU1nV'LfbR +*dF"RhGb>s7NX&K?#u)F92;!%pE?$iUZcIs[3EW)*I#MYnYVFEs0jJ`[HThTlejn82hi4Nm8U:V*$+GM +E>bu/nMk4O5#L:ag:$dQY;fM1\:rf&Cp0!@;5(9sc40Jc)S+?\;,e6C&MZ`AkuM9kj`"r&e93W]eZMqD@,]tr +,W/]KZ;:21fC>BI#0FUBQa&=0d4Bd#pr%1<>>Go6lcIKEr$S)A1k?HY)FM95IVG[NI+:G>=bql_d8%t8 +dZ!k;VMVL*`Q[lJKCbL6mY&)f4;Eh0;?_4#;^mMI1Njd"N+f4H4`QFqDfYLihf82a#FsaK^#t$5L&KkD9`2fDBphGShn#qnnoT\aW.P +hpgF`jW+#!S"1ZONYnV_8=P[s,IErIf^kc8S"p+\JhMS`i[^C-hX7\f"7F_"`bjA9k[.H&Q!^Y"F[s0] +.W6iN$G?ebI4As!ej1PW:_+RqIaI=?X)@K%hB3;3o*qg^@5@ +D5u,d"DiRc]qOiGfgHH+'A=gXm('j6,OUf+Q2+6>-bYPr^"9mN-it,WOoh=gH643%bp"L +*n!eRU5JBL,,JE)G@fKs=jF+(?!?>tV\8A0:]JlrFjV$a*:_AKU?KS:587m0-1;;5a/Whs3]-AHbns +=B5D:N+E1jPknqpG.Xl,7s`#Z&;:i)]GM$eXMED5V+)0\Z3'o,h=,7\AHbmh3Ei=;/RrlU/$S!-d0cOY +Y,hV#=Fn8p!]Q[!.SBNB!lRSe5.l."YQF19ME'L)"ZVOH!aFMKB@QCU!kZ4L!,"m*9cdF4@c[0e!k[;i +@+X-?&;:iAVA8#BBa%>DpfIRBDi^i(5?;0QK.]cO'aRJ`YiSNQMY=]b!3$`7!-PVZ"\:N9GuX>u60aaX]g3mhH]TV!dia(@.2hW +gjG'E[]+>FOZO_Fq9,b$k(V+:H6a"Q9g&ls +GV903]f+/_B@KP>037[GoS@.APGFsTNNHKgmIeZ*'c5c^q&Oi_'O9p0_(lA',p(*si* +Wl!Pd4t44q=fK`n?ku4sD$5E=k[o[`'lWY83QXE6b<9X8%%a#F`n8a?AbCjj$R^k*rJVWXXBEV'V3kCJ +]AmLbmI0VW3g]q89t+C>EQ("A3#s$,ETP[b90@.$Q0L@#^/a-H>d89E +5\`gTX8bF)lb$E_lhgMFUieXI32K<_`U"l(/jCkS'L`bW.nZ\MpPdAhoA444eOu&TD@'^3TLI@;knoCL +X\IYJ5'2lN,:_6B#>P`8&&##]L.Ka6n>!qjT@i6+BAmp,%RM.<=E3Akp)c$KaG-quo5SHTAqcI*cO.tVQ-a4((!df3ush;U0XJ%^4C@E"B%1ucT&'C/6O=C4hrBcc-Vjmio2IsD8Z +?Y`,2Q"M)iW._F\-4WTqB5lkNm+j,Hi1XlBB8/I`:5]1ui>Qnt?^. +33^/2LcD\""EEK=s$5b1VMZT+,EAiY+c^Ap2SS&_7iXPPEn`=/+KShnP`%iaK-[s-bt7HiG#JTbjI@F" +4hcNCH]7[`5@gS.M@+O=.*h8ORRMA&b*o`@`C_QA/M46THG#rA5NXW>CbZc=mI`E +"r<$(E9-b./EcbB9K9CII]pbE[2R56E_MR1`V3Y&jnEN6n2S!2hlAKZk4%G\EU5(4^.6P85+L5?:XZ0$ +/*)tF2Z[u%O?ot1'K?+ZM38CWn\("dSGq9+LD6,'gB8!75579>NgmJpmLS'FOZj5Vbr8%:*cK=)'U +M]*t-g;21?MHgKQ2eRs0Cp4.^4c*D9^"<.S1IC#NPph,2b2L$43J./Yf:M?V_KdC"2rXoZ@I./ZXsm+? +TVBL4Nq%-sI(h#gp?J@Xn;?K?^tcu4?7@.rW)uk:WHs3[FdYb^H\%cRQ882D4i9ae>/BWr8U*1mWTjrTY?051F_&gaW%!j^8;hn"X(T*2 +QZ^"!lW#XuX.1@,LhK6ML26duLRL5U4CLY5FM\<+].He:4*&%KAR*GBk'fr7p@(#mpS\=7L_U2ad+RTB +<2];fAN]LKWSiMc_;.*pp5X\6uPdDatK +@g=*]\%%'ODrrn]c?pD]F>;YSd\CFgBL-QYf$k#n/U-=A,!.rYuXI\I/E6Lbe3Yu9K.^%DV4G%XblXBd[E>E>JZrbXQ9JbWRGfdaIeaKe7lF? +FQeCeQ_JMO[,tib&bo=hkM<)eGu@5*UFI'jIM[,._CjC1SZj_&h6mQdZXfC,A>A0AY2<^"7Oc*9R'5RsQnsrPEi9B?QGLl+KmYKTFJ_\KLJol(Xkm0'U%m +;<-ue5OHq-Q7V1DbDh=:GB3=5bU7/m[RWT+i,8dcEK]35'Ld,WOPE&q!fOHOD8C8##t8nS4Wh\d55";O5pcds(Llef00./=mH,B/q.t"k#g9 +2s$%Dq%[hj4QEC/n9b_knX3YQ*90(XMDL8_L2fC4=rX:R-VGDnWNfK%Xg@j-enT)TVq,UW\)IjfogZ_/ +1[2S:a'3Te>M%lQk)n)3&F$m2ek(?!-OV;o/b@?D=!(0/p9-=#S,E6FS2%[X6=h8lgKkX9.pN/@s"SXRrq.a=WQT5d$T$#+7o8UQA+_XmNP(I[Bb>'qC"e +(!%Q*$9/"_:e'9a.M1&Yn4U+qX1bWe;`q.uWjc!d#f`,7fWNe!/QnN%nZiMC)O"/D&(<#0r3crVs-Y)k +.B,@`]+4fhI!NnNrW1(2f,G+`_Wm,7F^]unr+eLrM2UZ9At57$qREk@&?NZFWG,M/AP:pZI?4Pa-%W)0 +:u5]n^DGEJk+tWZf#bZ!)dZ$uCrP@P?>QsW3pF+b6Q1,A>NcF\O<.,*\A)3kBG0Z<+&.>-;eZloFc[rd +roqfU_U9]U3leu0$r*JbjOb9pMOeb-4fhLMQ&;>.ZJQlIRUg2F2OWaXDb[MPBC!bu)Fou&KdIt?-:*ZK +1s)&=V0p!/X21m#UFWi=*L[+r1et+&1Tc-U+!qg^+Kc@_Gs= +8O.:[$Ig=]RNs9VVMVspN[EHVG^uS`3gt^a9MMf-Bhjd"&cJVdCjC3J%GB6(KtDrdIMr$ckbTbc/89J! +apu[`UNXmh:@_*+3mUkJi@CqT1,oZ?cnafjU-d%2gd!k1it\a_B##cX>"$.*`$6b=%.XnhHI>9V6AqS8 +WmDs)7XN_Jijs8Wn42hg?`c9e`qkL5'sD9p2VVhlMTWX2#!SXE2iO7u +kHLr`$/[,%9A-1D[1:*GNPJ5.X:[3Da+prYQohJ%b]++n;F0/9^T*3:er3ZH.=@=lK.sM,<)O;31A]=p +-h:F8VTB0$RFt3V`F9&KZo*O2R&;[](G!63ENK,G``[se`3JjcajGB&NB)-Q?lmfCLW##:lB_\-H[Ka4 +Q4La!;7D5.ViBjWQ)#FLSh&O=J`=lft+gN4q=>qSu?+g4]8)_t= +WW)"E&&g?qPW48rN%giC?n4aj?]l(\11/,#cWARsn1^U&6M276oKOgo/A)p)>YB24g'nGYcE-?<8A!!D +3K%OW:fD#s";g>B9oY532Dmg>*Vq5t7SohB%qYj-LPBjCqa"PfSBnpV^hVrk2bqL\=ZSkJ`h%2Go6`Ve +Y1^.?atdagPNk<."E0DM%E*DTn/uFF?`ad9*@dtFXoipAQ1(8N0ji&.Q%",)hbR86M%P)oRf"3]nY+>/ +T\-t-G2E"-?MZa."7USGh9sMprY)KAb.p("H6]ZOU$?RgFj1;,iiW^"BD!daS0tojD8/d7Od_FMU_LZd)HqNE(>/ +_YR!ZdBt#DkZt\Z<`UrlHJNbW[sIG28j-Bi)HE20ZoC&>>Tp1F,`Um)JCah[=MHJAXWG9=qee_2JH,J>+g"gZOg?l&BH6^FF2\9o$-%,J=BT2dMLRcu"T&mZOMOGp,+8#PHGDQ)DhHG&s +GuiJ$M;9b`RMc(.0@mhA]m0o@e-F$Yr(O#,<=OQ@m@pUH=^UD&T6MXj)Oq[nh5la5rA%gg)InR^X6&QR +occiYMmoNQdAe.)K2l9opSulPfnZu_b56,a9u\Of%p#FY\eE$I5)bc`R5;FV'UhbB&.S2a3%F\WF0;;dOg\IhA9#-+m%P\72$bA-^_sMM1A"Mp4Yg4muR:;m^]U'qh\K21kiQ/Z][?IOI"UmaKXH$Po:J#0V:pkA +kYK\93[&E9]-EN=oqlOZ-3pYgO)kF!Rd8UN]."984Rq:Io9I&44\cs$X7?2c]&1GmBO,n-e/!P5 +pU[M<4W*D&4#9caFanPBiq:e/7aI[7Pf#F+BXI985 +;hZ-lW-0ZSatuq%#^-@0(f(GIR]u+O0"]dUb;Sp!gqUsG"TdBQd9&l,j5"%@CC6`iB9,*NA"uJ?A8\:WlNKY]$Cmb[;=;Vo?]C/rL.nrd*VC-la@p? +$(jmd9m3H5_YEQ\*H^u?nB8?9M[]P!fk@6,IOk!:bY?8h@kTdCN*FAp[@Ju?\)ZZWZHdjWBstJ=^LY5U +\-;S'1tq=^YKiD4'^E%1JjP+?\q/XDj*7p')9%4%`Zdk*%%B6E(b`A@@a6HMjRZ"`/L\uVOpNf(A^Uhd +[qPO+/m?+R^YG/,mW^W>Rm1Cb0;K0]&#\2:e8DpC3;;@3SMn1t,Ok^/D;dT@>#ot=mE`T2=b4?fP%F?@ +)gHA4/TP1,iZ?:p.3AZe72=i9>8O>3:Ed%gg&Bi49iF3R!Gt3:\SlW$mCfULNAmiN2r6o/3jEu1Bf2B7 +;8X>k@MO7N>']l^[T)3e]n +B0@\Ar#&k$&PV#/5$&@rA$j^u%GkSm#-p1rgXi&=NBfRbf)&5\R@M%.b3cuFc\[tCo/hDA'/!F\miV%@ +Co7qG!&6='$T8Q/L,G=,k0<+&HSD'\3sDH@55_PJ1C&,sG5L%$5C-$Htc=BhFG9rS/Jcc +dC#Q2[oh22Bhn(9IPHC@UQBD$U1s^R_@gt&Y$M:Sh)SI[5LMj<)Eagr?-.D3&\X%^!c +:5a.fN>8M])K%G22>5TV\m?-MVYrWWeGk8Oh9taVYq#79g3H'!&(rD:Vj3ec"4[ZLSbZ!Kmi"G[]ufqaU;JTK-rtFm/@fsN_YCthR`7QUkVGEdLZ^n,dJs)R +52=_VcRZjnT/:*7Gi:Wc4=JK*W*:>+Q)>+cXZdWqZ4bDG[#)D]>-SDSEp&^kqn)!;Y5;S,Q62tS#$ +K0)t-?W,b7lb#RMS[\<7?D4LQcRYe7cR[udS6'%p6X/i#SQCK2>FFNa64:/m=%I>&3_47md&k",/'n"= +qV@qtn]UJaYD=t+Koh'+/)6KCH0*TVn#25;eg4kNd(7_"?C,t`Y=l+cBjL#gPe_&%H2_\fQeKRI;U^K' +\^`^B95Wj7ajG7Cq+Fr"oj4!=H>@*krY,1?"M;(m-2*;`;EO>iWSP3>[@>bod`-R;iP771(22W?U=eF>M%GAj^ +W&$M*@+\$tmt_c(grjV?cQ^9K?n>kHZoScd,OM201&jh-SIff4kcl?"m@FQ!ATrG?U>NGQSVOZfFs)i/ +^<1BA45PW0,PS\Wk[*CHeneU?8>*]QIGO0Q&aA+MldW6mk]2r4'60_lHYIt!l_[_`D9VlJI-;0odg+S) +pnkrBc,mT0fB3M8UC&H1d91QJl*!/%Zj_9Hk'M%!]:Q4U9G_:r4FUpS"kq*lk?.Fagd!mMXhT(VB5?9X +3Qc,98+="F"!W4jh&AAcNL&r2(Y+mee%\g>?2+ot?p&C@?65"--gJpC+Pcn.O:>"mpM].dP;G\Gm_`am +n_(FcmJ"WAmqRPe=3f=SHSd[S\&F36/6(>BPCE>$=@Yp-V6s/V9?Fd)K/^6OHS=0PgPVBIX!14-'7"n8 +='Cc36d-C`kgq'O"'3\%WiR53dA0,cncN2$aEs=mPJ<[\o5>k+N,3C@1PZNYQ^@\%T2F&aH%'Ji\Uo&b7@/+,PAT2_ar?o@J%6kObQ6jlY*eXa0BHOD[XFF,$M*%]:( +GKj[%_mkallZDq$TG+)FFdH2bNIr.A?>%"2';'rGGHF8?0.g!pG:B^b8\$pU6*)Dhpl*`+e;Vtq)tW4f +KWR(3LoXM`Ecnq,Xb=-iNoNSJCj41'IVZ3tbS_)!.A]odG=3>O,t^ti4q>6f)qX>_\NBR=aLZEA1uodn +"+,Am%Cr)LZ53WA!2oS@W]Y1,#=n(!O8*iO$N3jaa]=C6=&3.X8*UuhI^LZP])gT=72Z`gh+KZ$eEZ=%Vfi".?/t!#FkVjodd!Qd +cX9`_0srdciXIC36s&L^@moSj5,lgr3Be2L8)'cq_1f%4/F0:BgD_qC203e8ZX&%4=gZY>H:WrF$ +FDL8pALi8E6IbSK<%IY?Uog.I^fmDm];bIZ[F]bA?1STZ[7XBc]f/.IbgTmrotJ,jqt@;O\(>r`?L*$?EE]0O0!4lPF$=N25XXj! +D=uNn_+Sg5V/?K@5"g[3K_:GA'Mi&`8j'(1c?QX[b`f.5&(25=;JW&YCHLb,H0\d9lEp+2(G0HcBtf$E +\p.un56E,pK)0^'+lBX/jj'P7m2QB->eYSe$0u:rG'iU:>C6QB)R +gZeL`_73M0#fN]kluY3*[?fDt[=6:PV/.*11u$EQ9OGaf0')-%Fnn$PDQ@adr#L#B[YjCC\9;Fihj2mT +'?B_BhC%I[Sho_&Q4iZ66"\W7DO^Z@Y?"f\,9Cq'MVeZ!*[-iq*.U +*Y7_I,6+?tcq]Lua2C`J>Mh7>N\=M:[GPpccgQ;AkYYjh)7-@A$uG`DH$TOO(/HLF:VYWF5,e;%6hF]i +65][g3mA63R7+.lp$N3.V]ajW6"fIfgoO;(Yt\"9Na!tS'^$[XcTZ(nNof4:X4DptigNmsCS->MY[Z]i[Flq%uYFp+,l*QH$lOd.1%b/J&ZO7Ac +\l.i@kH:s9WMbNln)e)$Q?kB/1II!c[RE$1.H=C(3Qhh*.*SsPnQg<55g>V/f=q7o0j)>N+d%_W&q[<=\L@=5_ +'n:.r_gPDHO@l0RU@4.:nL^57^#YG>j%H>8p@JDa(&MO_dGh=98coBr&HJR=)LknZmr&#\MP*Z+=VLWR +)H%9qB<7D&(HDo=SCGI,:J!^`MK>bC6kgUro4[VdN>1gj3frr(V5dP#cEB0TrO1>!4PkhLAs=0LD7o+6 +oA$cL/RKC1Y_'oH'#fFDj7oHq*:F>C`)jpW(3/;e?A+r4RrES!jF*S]rW^BD)fKk+.4cr+0Usta.Z!lbP*WfiTN)/alEs2ia4m]ppT<*jcJ*mG, +G&=u`e=8/.MsmL>SR7hDa,X3N-_?>6kaaPRs58$Yc$IcFs$Eh(_.:-\;F2ZlfZ"0V.A*B9+/W<)m +C`oq:K5TnA5,ed#rs$5bX)%DBEkc2)n'^j!g^bE;lXSL!5CS[AHH-UTG_Fh9Xd8`Gb_'J\C.Tii40?Zn=`F:HntMao.W65FFe;6-]AcV@".5t<6J:+L2Kn7/F4;>^3d +SOh4ViVCi%O^1@<+tBrX&BB%R2u(>)+rd]FAi?1i0?U%E%c3385XX3c@aqf2`6EpI-0m;"8^6(RLW*I` +2u^*6NgB,ck+0n$0gk4.2q'M^sr6@(?)/U;_R0:Ae?[.dWpuM]#X790DN'-@')u@M(0(bime0,16*H=r? +L*@uf:W"j`G_nIj],PK;G=9dW65NU>(3e7?Q/CQjH*RhM5g%.mgeD."`81/RH?XBmXR$tYq`ai+9'Nag +UAr&,p#]XB$RcFtIEk$i0(o>3\T$a1&3\jo#MDuE[!-Hl.^ML;H@DHI +qbFm^l.rQOQ,`#i]sE0mF&MIiF_Vn*f/Oe8U;lGZB53rs&\5odh2Z9@^:44`NU9]/1_+P?GjF:oVK'2S +*]8uFeQh,W@u3%&,AJ3-C)gdYON+Q]A(!?XM^".5N%378aR'QXLSJjK@s^/d3$#Sh)Q0&MKuWADl`b)n +DYkJh*$Wuo`7-bP.kQ'\RQ*-!f=HX=C0e\Y-aa4;:*7t0BS?ql`^*(]coA`'^".tY2jq\MQ$o=FkuuuD +EOqt'1_/D2NPk4p`p(pLVK(6Ul4isL2%HY*HL%<.8phHoLNK60Z#cXT*(SL<`7-d&,*JaAqPG%%`p&sC +LM7_io=2fF;chC,I1T?;FKIm-3*i>"]!#FG1d.OP5[e@H,1efme2Y->4q"@)ZGrRX;<&d3OE?ANC6HR; +]tG/D9oWXqpnVo.'rZ,N0rT)tIY#KVS\;%8I2$#93+Mn!DoNFTq%)8'XqpGeY@2PAn<6!@S3[TpEpN>!?I'd,&M#*#HE?YqQI[paj&/L@F[8;kZ)dgQh +fP,M0[ZSmKj6d&PNR+?6S[:h]gOm6fq*kq7OUZk"n^KB\^;/&aKD(=1c' +X.ZkPM]R;VdJG.&PQq-4R&dE#4#^UY)t(L(W#;>b:6W(mno6^hfWZTfq!J\;Qeg.pfXf2@^H;\Vjeu8Jp_.]g-2QNr$!."fMD@RUR"\B9g%Z&t&@mRFA +nfE&P:dWd^goQSIe=dUQUOm?%4LlhCDo`:]:A;lKQ,kl_:pAn/`Tc3G[FI6co?>_h3&?4IP])RD.bN+>RbuGkK8AA1>Dr(6D7B6>2qfA#X4.![aB%rn07@seRYO&C#h7b2>GeUo@0]dq^Cb;9 +r5E*86G8rU/Gf$Mk?(!j!qW\EVH=AepoNr3X^b<4%%+"IZ1-oE])UjeLcu_!qp#h32i5mk)Zc7(W`sb[B`HWIrH4c)$8s#F2=&,3C=$P^ +2BQdGc[/5l[$hd;3LSLYr<$K/A4G;dUsJaCI+..Y7n>W:"MQLq!SriOp>7110D;-%[q;?Bo[[Q;VW]dL +ZeD4KAni0rVqWeSCNobaSX-NTl-Zhq\M-+UT:.]Tg`8%LPPAmm&nWrMS8Pao79 +i`>HbOm8AK:Ln/&ah_(oS)9>3'U%j5Xs=nTJN +XS22]9=\F@o(UK5e;.A#GKBn.5EYmNe!@*s6n[Zslon%WYWAY(#_SYWT+X!R.4VbV%5IA@ka +qZuhm;o:7Qh*Jd-hcd)OeCj]3Q(a\Zp"`/=Zeh@\la%q.5[DqD@b1[nC:/QM +,-)NPs2:23c6!JO0tH/4j):[DjJ8V,iE=R.#1ntqcBETcNr9D1"(9K@=WnlYgr`9J3LK^O]iKFX327un +CbrXe.'Poa[/Pm)k8WSrV0]ja])Q5T^IuhqkZl8:c[XrISPCtZm*G,F."BL6fWesj#qEHs+qC*H0#4Sq8hH8ls.Hk5B5t`h4V,+S!F@[\2#jEO)4e+IBMs%VG=O^q +gL7>$^Am,)U34NUK615LOcrDIb:*cnoU#2mb;8\:Ss)qpDk#U:qdfXt;WsO``gtGIU'86@_a)2mfRKET +:M!$X);BY2c#7X(W0X[O@mc9`25iH7fHon;`O0`H0E5V&)1h7Yg:d*Y"VJ2ai$J>M9;"]AB]U^@Je!Zn +(6o7!'.J`r^G#T+ro7_r'7O8k6X[Nm4*fD_dhD$%/nLjD=1_[pRD"5#3]gP+U(/K@Pa0'Jl/[3-H1VQ> +]'cko%Yf?qB]si?h'"T)X&UNF>ALFfUYO\^:#7ZfjHXQ6^@Fm:N^%kYL[Pa7;-+`8K/U8ehYQR+\,ISC +$%pPhOj3j=q.Hl(qm9nh`LXL*"'M%Bgl%QXi9gEI35F,31=Q&*=qRng%a\'9>I92c,pKS\),]^D0uaqg +c^(RdMDOHh,8W5=Y/kVfPUPAK'6,QD+C$p&O]$Y]95/.foTss\WaUp3qmA"XB+[0CC?0(MZ5$< +i\#jQ>:EK3A^JJG[8&80Fk&(_9O@p@)"p0_'ofZH):4@oAW%TP`X[89s'lj)nN]:L7oC8^?$.2ABZ1kddIT]IBdFbZf@p8E6,1R1I::M&qdVh(0gkQ?QPsGKp/8a^deV<[ +YM\M%qHdo]9o6R3)h%1Nkdc$cD[HKB,qkt*oBV=k^0_XBn@LI8/NEh.L:5lK6E5B-50>FV]Mp.JOmp"h<*B0e'!`Q-RRjS^BBAjt*#Okj+-%6Cj4Q!2lf +^?GG=;qs4H:]*8T(A\[;)[#g[HoEg\A9\t,Flo;Z:lJdq%s5P`QcQ+upBDAEHmnU0H\AdurRK%:Sks2o +RX\t?haC2,f\SL;f\390Q$U9!G#@U)o +[p-[rPUm+MtraaW[EZHMd]H#DClZcE$/aT +6!_],KDUD5@I'5=\s_MGGFgoANhM[-iuiN_>:jm7Iq`(4]se_g%kU#g5+BHB"'^JSnE]Y +Z/Q'>a+mcLqJVsn/G4X8$5L+7GlHaur,c%`_\fMu_6f&*n#_f6Z`dEj=(%)Fh"$TjO"i/O1WTiWjuJ=8 +,H-K>)<$*<+.!QLW"C$_e3*IfUJdJ!\H=]4HZm)+(ZcgZ^0H_<5\/)MKL8ZR;r!R7`_],a36%Mh8NijC +:?[t>B;&u)bh%p[89%(k\OSWdc/2DWR,*B,%dd0+FWtK_g'-1VQQa5>OGDce0B=6E3/EpG6ddSIl7tC* +):fY`cji(Y+rlR>Q +O)Sd2EY,@S'TqJUUj+\sI$IqDSVd-[UgO$@,=[U_:EN"e"1rJMfP:=?O>X%0CQ(m=Yo+D*Ye84;PW+?k +d"j(<#Us,L=kH1e2g*,h>\_p/\=t6?ID9p2kCQM\njF2,BkEOHpPPjZD^sVjj*aP&(frOC3J0%c;le%> +i[lhL5@[BKKhjEp>H;?6@apF3eGnY/5?^.Nohs]&qW2cS]hcf>ffQ,:?$/e0U:9dKiGD/hX?GF@bU3q@ +0';X=-?_A)dQ-BDLf\Wp*OttEc9l:P]S1c]MH`IIZg.("Qd6k%kYeiac%s!0Y2$b&/Vc2u*kg0+XJ'9B +lnl>SXrpp3E7_$jUA]!l[ArAEB!Ot!a\U-742hlI]BuU9U\M;iRI.X/]XS%'2J_$Wq0.kVpY=OOW#$h' +!Fh?];tM#tK9Bd64l?oc$H=Wa4SoUsW3uh>]lN4P,KkDL4H>T4i$^]@:^^0m.q['a8f>Hlc0YO-bYu]s +fQ$JbLcBD(Cr&u/e+9o\GE&q-c5!&&ZqeAT@m1KQmh83Me`OH8nS8q"`Ug=n4h(gQN=N=aVfH[7Nd!H. +?acl%M^t!*66b;O'#TU)?h+]meGamkHZs.h#q;](Ebac(I:.79U=FHN(<`Em&`:4-^ULguX5jouOnY3P +0c$dNc?=6hH\2fp420!e7QjU&dJ$/.\?'r$o8`cBoGT@P/uXiq5Pk!as[)oLmico\PB_ +e#Kj%k:3#GfO&")Am3^neb%&('gf7537%pcAUWC^1O:h.da#ekd.$C5>[RqG=nBm0CGMqkiE\&#Xp0Q-8bXW!;#Tn7f1=C^ +o?/"Yj:BC8`ZE*RD#CUhM@EHF):^UdJ#47[aEFCCW!=1HZ=S/EoN;]]B*=UF^Vtu!eCs[E>EsE-?K#2N +>q,^f_76PsOqpTVncISFG$"*\T+$+nH_I@ZUV"V\`:u<*]'F?ZFrCB7m7t?naK34KZgGiNhdRtAC_*7ugEIKN#$t-5)gI;:agCKcZX?5l^&]NAtr'8Z/pu`9>8_j(f\QNAZ7r0A>c)K@Ja2d +;1?5LZDbM-Q.G"paS")Yr7j>RW_S>.@8^u^j5\V,?QJ?$!r+>'bLgi!c.MT^*9O0>GMI(XWm8J?92,5D +;o8OPYpOhI5'c=s[??Bi2p]4HVqB^U>*$,\:c\.$^KShoJ'$>`^,KMbO*54BoQD:]rq]g9Z'EgBaYO]: +I[YH7:.'!.omn+"f^d6Nj=&+cA'9]H>CJ(!Hl9\UPt$mPQ"uAM!)L^Pf$XIt](p+8[D/6`(gF^MoU(l: +J#7]U%l:YaaCED7ru(?`\l0423I-'Q`93BH$o2k+A<*oSjh7u^RcAkH^:r#jkM5h-aPXa=382FM4I5lf +W3OV?O](V7;LKKAi#>V;Dj-K!1fqdsI^SK-oUC"pM"2E,oChOpVl$MCBOTEJbu0!,Fc/ie?.:HqnQ7YA +q:0qd;LW2dg5O,<+luf&hf4D&Aa\mScG,cUCk&SZX +7(f%k`J(r`6H[E,0'-/\$LrU?rn@463*`4QrF[\0i5lKb&m-o/.>;\&(dY$&1?SHe3n$mEP83Jm(qJaD +T>asD9`._7=Dkf),D[WR)0t^p)0pNJ]=eIFg%r`rN[5or)D\$G5t:JeabY6D)*tX"UgTG\g=m+g78[io +<'Wojll0dWjNEpL$!^%kNbfeAc`SNcQn1fK3OqH(Q1*R3Z +N4eq@&WJiJ5XpDM,GT@plRnj!A-=WBOqCQ]0j(9,9T\6s[2/^]"=Hf26lF+fe_49C&r180WW/3F9qJp" +,6CnORO;E[quK<@i-s?9KPSGlS'.0Jkc7/51\4!(hVu5+PgEL0F-H(0 +]t_u`)@]oOoXFe)l;Z%&HEACgC=UIe8C0b3;LHQ\O(c3f\M%$+g3i;]o_^(3;6tDlA&5+s3`QW2`>d(& +dc1eOitOB*)YJV)$JW`>2d1Xs3/&TO:`'duZ3d)(a>_R5*r1Q>Kun1q[^)::-4Z6`gtZ(E_a[&QPqA:W +Y4Vf-Kh$UDKHd/[KM@.4J`@8#k30JN(3)_V8f&YF;#>`1'OL%+V(j:0eOnCsXh==-X''AK.UTa6Wc;sT +LdLKX&5fAD77:RQ?cJ16ffV7S=$@Rm62<=;+^]"8^3$;.9ujUSkH\H.^\2T@XfNh;/EZ`(,#n3ka^3u- +ZFoXZPSm14FXQk*JN2m@h_Mj2qC3tLX%/-2Dlt7E``?%(i>s&Te8@_D]p*nlp%$>V'4QG5MK`2c(n'6g +!gqPKeX+2L!fn>g+8MaK[bTi,GWJ@QaI\+)?EH0n?&Rb]N(LReD%0MV656&*$?,9=FGm0-#]JjueC05: +d$p'A/?6O.k5nV@))Gm?Wg[+@Rh5Ih>9R^9<)m0@i[7-\NRaFRhbHO>JohpBS`h#[qsO+=7G3iQi2Y7* +$Z`SoIbm!D;20q^e>fkO,iX^"4q4(k0KZRhRa*)aNZ[!Teh@%LDY]9J$bMiXm%[%53ba]sB0t$.m=.,o +Bd`..l7PtkR]U;MF[se_IKEs0RD&M104Z4(#GR`\.%_JN9H925o-9Fn'=WHDb5#uBgOC7*CjDF#IKNHm +^r)q9;2lo2Zel0\3MReD@&tt1&e0nB7fAiCDlDcBH;N@I49jGXA,`!-]i%&XD2;'7phIR8S\&PM_7 +<,$a(EFlbima2UD7:c'0J^psL-tcMDl5o&GqE^ZLcD[tr)GJE`Z&.5m\c,rqb[f@k/VqBV>ZJ8F6aqm`mi^Z +\#NdZMC[PA-nfu`1Sc'(Gmm$25L5OQ).\sfYt$fM4*u-?3R90-[`F_#BqkgU6L#_Kal]ocNnNt*'A3Z; +X7]:1$?Io].u\MW9MF"bCYe?>q/_+A7l`Zfbkql4;u"ND]s?,mkaB8jY)p3q?M,^ZN+R=!ZXp$m5%G/c +BrD\21GWQM2KG3S3R:/96:=Bi#:VQ%]PP;QrfYYEZZ>1Ga+i7aN,f-qSYPTX8(i4SX[g^gTSqR0a/83k +:*#7p(=b/UgDK$Glqu&URSh@X';M)q/8KL>?@hL=KR;q3rMCZD:CPB-b +MXr'`D#2X6#X0BA="S9*p$(t^aNi1$q<6irSm?U4g-$0^Xj$+cZ1eE +f'/-u4!4a8TT^uS*jJV+>34`nPk`BLYn"]s\KPM0f"dSe%Jmk@eqGuYHLi:&1j7)Q_]$Mg2U<@L[7b)T +,\1$Td=`.G,PsOqAL=70OW7*k(J'l^R5fT&T:gY^fWon#XF3ZL&;Lr46QFdUCi0$e_kV=_G2$s%;79\E +gDbM%&&`qpL*ODB[.qF^6sEhG13-)tHfLr]Yj*=)$DJQG(^ZOQ&,(;;D"IDbM8.aP1Km574upg"Pk!g0 +eok2/B)XlU^#_:pQDD=%kU]U6nL0kiNU/bh[3!I>U/_]t!nT6rE//83=.5ldXXkVcF.d1]ha>sJJ!6U, +%]*.P.Ti_cXb%RYU/go6?ZB+SUBJ>@;&;T0KD%H\la$?M/:3ZL<,3WNd1Ohta'[7bGBA/,+.HW6+.Lb] +4N\.%HJd4u\6DA.b2l^IMh[*iOhCE'-qC.YeYiAl)a[.[t:t[AEgefeH\, +Z,qjja!RG,7s?6Ak+a/YBU.(sO7g<1'=N;Ia9].t$@?:9ncO*u6/iBCq._U=e)LhGWmf:$A*p[o1MLDi +A;I^`pN+-9rud8&^>?k4/+hn@E)f61jU9+RlZhA[eS5\'QGu`UW!lFEM0YcYhS5ZAmg2`8F +Qlbu%%CSFJ!BZ4_N&B+ab]P^qIRHCEF&%),S=U6rU0S?I@kf1klBK9_%dd]?D6dTo&P/=2KKYg`4ljjH +%Z\Bs+1Oi'S2;>[RihW=1(rO7Mhp[?7;(Bs?<^U]7bN0td/tlT0Y;I1Hkq1^`Fn:dQ+Wi6C7ZdajKX&J +".hs*KVWh$5gB8V_If(r0+lf!b+S+(WBPi>pVBpd\C^RMD)O4/m.ut(BCiL]_V7/`B4&Jn:Qr7(435QF +SC!BK8S`?kVh'ti76BbFh1InWa3Eu'V-"7<>t+ad=B@AkBVdkj"dKeRrS[V1cF&'6Jb)=JcMgR2E9EfZ +OZqRR79%Ec(njP"NuV%rE\X?hi<YsY$_0jN%oM)-i5FFLVMhtpa88qq?MEtIp_+4)deJn-$T,^%%m$[ +fQeiQZND9E;AraYlWX5G`Y6'#gLm&A'a'2a(*8#?Sd+/nH32oK(%iLs2EFhSYZUDjV&jLL;C^G^91e18 +C`:XS_K167K]f!3--.QXV^tj@cbCk(GD,V"i;_!ft/p%1KQOSZo2qkCm%C:Ab_`NT7^Ik-#9L +&$&2giCbmFj+1S"';+cj!6^_Wpa+H$"Z<@T@i0qR`HH<8B>;lOX9>u#HgBhX2pps)n@\"dQm)-Y."!IX +rod!(S3csK$>"n)'\HADI4;D1DYd8NV6j*Oi/QC[V:^05GtU'W6,&T^C0d&/bgGEOj@`X=C29C,&UZ$^ +:A@_?2snu=1O["3c/BHj*$6RcVX2`VtWG`V(2+](BeJ\qD_J;YCSLN)o^O#2A33!=iJZU_L_51>*"Ab+`DfpB)s; +EHi1&VY>kaS!D*"&)V`#oAO[r$L'la$G7?kqFj3SVq8chY'bEHgmIIIrg`#_'_k1Yns(1Y>FY6Y$"(h% +%ik*a`)=l?!CfpOd1V7KqS1`pPQC3+9cTeiq5b:8pAUqYj%;\g0u +obTiHXo%St3;`##`8Rgq/%d\7-2]LfhW<0Zn%ju)3>u5koYtR1[)=ro?Ddn?.On`lX`j_je!Cd+gbUcb +HuheTR6^m8&f#s6\P8Cg76Oc+g9jjNLcIYL2`$!.Pue&u#M>V0`9NL(c\+MKgkHCD0.t_#C:1XKr_':! +S)1ca8!C.;7ZW(o^Q)0l`r%;).<73I*Uk(HM6dk%Q7i$2R8j-Q.`lTo/*i%G>scR@lk(IkM&[]/hPo>NAS^SY>jq[;Pt+2ZiCLd*5mMjo<,rJ6[,.JE +^HrH57dlreb8[r)cYdLHdILtM>q,*i@N.`R6^78n$9lrm3U8QEmn3LVW2EG9W4PhA>5Le?'CB_(G$s,( +OS^\@!Nr4JF;*"3f;7>MGbQY9kn*:eQ1S'Q:d)tn"iYJN)o#u"0$L2mmP\fliUm&WhU(iH!B9mcDiK\W +EVdJQmtA+#Ar_1Jb]r*8T3ppEIHgY$Va3ebnd)L%*]\p8@.4@WGE9CD%'ELB$#p=C9jI7DDW_cYHhP*U +`N>H*AoG-J/@_CE=a=O2l5e[8?Z@!hB:&=THkUZlk!e3TrD^_=ZLS9J7$$3U3KX5(N[@q2m)2F"Y<5-$ +;*Q&f?Vr7@X5V41hN(_ZiR=kjEr:$jo66E8ibA_Q^3&+6)@W4ecu4792?Z4[mI\A9Hj<_gfZs+A?5X&i43#mA^HLHTcEh"0hZ9=)]@l9V +3%?6I= +=$ku^'&jaXjda)*pA+17nWpB>2':=>S(9/kCc^"_I)FoF1f@\_?T:ObfRJ)"hmYQ2\A*Nlq,O,&oCW"$ +q*'3;rFJ/n;$FFn)tdb9C-s<_oGL]P9]JidXRgV`,]`])ApuN7P535&G!GOd2X)7=GM]$uf\a2oh_jH, +V;K`T#J[#-:2*R+#AIO_4X01UAiJ%`]P.o$h-.HMkV,QF:4Mb)'MS/tOX]_/PH;KTCPY'nFb=#cQfbiA +iPeIlfT"/t-q:FcAm29lK<\W-+hfn6.%/!/k)hMTq\tq*>%!sorNb^9j`R_7GpfigQe_,&qJY$T"?NtQJYd?Um7nel]H=m%=EO+aLKQ!c)F!6BG66`Qp/^QO +&P&KWLuJ]CljE@sf0l[_]t*,.mX+\McWe:"B4L[VlWi"3T-ID,!"q.j8ACA@%L`N\5lXUWO9X-QWhmmQhkGUa;_j=2u)=`%FRI`Wd>@s8@Q6aWKm&q +50+CDC:@p($PZo^iD*0/1bHAiMctA9k7da8IGFR?jJC`*,03E*`&[Hfb:;(FgB0KaZ>L)"9.tE> +4<^/[\e]&03`jbp%;b1krhUq>a\ +U9rkIi=Q4A:hc?SiMBl&`[\R@90LBMc+Wl0VGc3=I,q+>P%L4FO7Q(N"o0][HgN@'nl"qC:>)=jIX&5W +[q\.Y9#uF*WNUL*XJ#dae0u9UJIJ[rqe;r+=).%'q/%j:@2nlQ+ +o3Tjt)K.3e?RWS:O*$@-0D-P'%oVfh#DE[i\1n6a[U(C-q(OZ(fkM@1l5_*GIqO#*e+i-j*VQr.PHD^Z +nTK2WX^>"5l=YnA+F0ri[F.]b2nH*Bf27Kg3-'#26ofV_$8498+YP^O/2-Z+'I-lAV$;r!IQ$%Y4Hj'k +4MHXr:\7Ya#k2jf26hPGcRr\.\9lg9`Qc&0ps9s\XY91Q%/XW2XOM:==O'G8Z+3HgaSl&Q!_O +%B&_Y)X98o_Fk=h0D4K&i2,;+Aps>>?Ku*/QIc].$_Ln;B@Y]qHJK<`^UJ62Mu!6_l4K-HlLXr$90G:f +nkr9+PA^:mUO[7[%<6@k)Hh[S+SFZZkU'*t6dJM"dRuaXX0keGMVi6VDpk4\-.Qg#O'mf%[+n=AfIUsY=aCUY1H16o98:uQUV%t_.k)]d; +_+Qq.1i_PoOJ?dTY6PS@s%hdU$*K+cEaJuUVS,L.mRl.ooTV_o(@Q^GNF$@/pJUTsHDtPbn'F_Pn$n^Q +]qC^C=;tnMdC@ET:t6?g:cu0:-SSJ_p#scd"Fo +>oNP!ps%K/(`C%R(OE&P1\XdOPf$VoUD/'@?>:\Y;?K^@WQcf,El<3YCGJ@42o6bOESnk8GRp*!U/B+XQ(O*VK9IhS$`EafpjU*=h.V;V +I%E:$r!VY*)5L%$[i!qXX5qe/-1cgVCUX]BrLZ(,R(BQjre)Tf7>'WIRiYVbhf,SbhqgL!Np$5O:Rl`Q +4!dCb5_X>jl;1[@=?!02Gl[SX0(jlQJJLiSO=b3l[J%brP)ZM?>?0PE.%rM9URnuef+E>gpg"K\,.)/a +O*MaV]N:Ld428CA'd`g)Hm^\#^9fJ=(`'`Lp%3r%NCrZdpp`VD?#n_n3i(Kj>r(cSFq#-EW&F=pjBXP) +'\o?B>hc:9FDB5Y:4:geC*:t%VH-pOQSO,8mUOFuL<9YQ\ZbDdlchZ$bVoGjR6V^`+$I?69V@C2I+Yp5 +H8jPD-i/rp&=GckcQ\(Ua'Xkb`4/*UWL5DXfhm\)/NW39bM8A$:gKYtR"_0bZg_=M%5r0RbOk#k1Qg;) +`j=2GAB+s7T@F4VG!WbaKFt6(4QtErrmJ'=C&BTtf5dr+GntkLh6Z&YL\]1>>OT514nrs%5!8O3[YMKS +:u'V5?@4DLg#1pa)4(1B[b;VZW>:_/GfSZuoM.0c +Ojfpp._3%]cI[CjFk\7[?>KACNj!?G +"uQ#*)^4uR1/H#6]*`X50(s3_N+!+f*rk#8&]/\5m=no2G^s'ZFVtOuqKeffZ +TpiVj+WF@+K?llmf?SET/GtaC>hqU0d)5I)-&&6?gSJ2bFtD%&k8e/8`Nu*Tm.uF%pVrb[DX]OWUUqh[ +rW21cp\,1XDXcmYhjA0po<#VWi)\[llf(IDP)oMN%FL7#8)3$d,fhA*hS20ko0"%@(FDRV*[3\NGg>:- +OoQ#Taj^SAYI&8-^OFP-IaG9=#$uPo%DFY@s%%#_o-n3c@/7#2p(-KH-SGFlV=O*@gOF(>Xas. +TUP0UDrL/0].,L=^T&b;RoZ[hJ_>-;<<_O.DkdB?Teo)Dnf"O_/t2TEoLX9-pk.*S]hlW>;d2D2V$.VJVde.,3%TWT'r2Kj)u9kfd-g/<-C?G='@*N&/Xr8=3VB-4/mFL.h6L+?%$Xe,V>:)[k1cXUK:VK]3/+5 +>:P!]GK`t<$[[P!R"h&6.NNHa."e,=H_G#\lM!n61Y@"@l8iVHQ:d+5eRZX;-AR:8!KWr">*s!XmNDRs +lKuhnh<\%rC3Hr'ZZ?ALl>?)D@#M1lYc/>*21eJiE!1PP._%B7qh(7!a.Cd3gft]2#cB1uiYP)^JUl2O@h5p;:k)!mP-(<]Q.($_Km<;uDlS$JS +COK"qC],PBYBrnoZp)7b>(=)SDdV?gl?2gX +[JoIX,?b?0$bAm4mh]9.p"/92R]2U\^>mq<^SUT>eoKC=95?kt6#UN:V)9B58+!DN_:-j/U^ORo.I:6q +m``5m?W]gtoncr>"&%s`_Hg='=%_'?PTspkb+.msoftf]Dq4j%E9&fjI;/q#I;01*rN'@N+/a*c`k*b> +IWo@=^P+.U9fk45(PTfmmRl#ea?$/j)fDQQ9!I`dPh`i&jk6Aqf4>oI>t\f\gseEU4)i/qS\I=7Zu=uo +^j?j-b4k`=A8.*X].<*-DPpH+KC3g1O4M8L><@=T)l^cf/)+,3MPZ"J6$gf][O,6&K+Zba+qL<`9QHWn?*:8;Nq4Uh9]@SA +Bt1S=3JT$?A`=ePe;@2dcbR\I\_(QU]3O&S'_MgGMgUkTh^og6bH'\Ag+i%Lk;@O#Hh<\iJW@6h43`(N +"%BrIe:2d[okrV&!tHm_DpTjA/TO'lPh5#k."VHb>[tHAE8`'W>4^rN`j>5Z]>[1c"i6CY..Ge3Sn.0j +/TRZ"c],``)f@o.,-*kBBOV5-%3-Yq(]?OCR[T4+E*%G'^@\ +#d8KdZa0!*.Cn0-(6@->'#p(!Q\E%W]baYr=$].F.+.cZe,t0>o4s?b)*%%>*M%plGW`>2_C%I>D),Vf +iB")tKTUG&9EQpCc#!:j!+"t.+3Bmr38X@r02&'Q#i3.6'P6-E7F +HBU>9`2s4]lZm)*Ffs_PZLO[c-"Z_'oCb*/UF'i-LHiCB)F\ +NfNLmA"AiV]B*/&6BYjEjEbQIpc?m,q5MKGK^@A89l7"e_!$7X:Y#tria1AbnnWmZjUq5Anneni>Nd6(V +q%15sb(lOV'6OL@2.n50oo9aoV6)aPb3mNpWWLG4(4ZhG4$1YBG4SH:"V%@FNn]Pn/^Sq65D\<;@*+B2h(5QW3bl +go&k\i74cRLm,;OYsPJ]@H"PmI#,*E.j'qOXF+,'TB5?8V57>jOADqJ+l78CR%V4?=$VGF/@$79d_^iagIi:5:Rb@cn0uEXGU"> +f]uO6Yq*'3WEAnL=)0rPN^'f^e1^hJ.j%gZDi;plFNd9R(\L^T#KsB;eCpj^;#*q6D`A2ABXXeEg`8]L +W-m7T3gBRAM>sp)L]=O8Tm)%4+92/skHDr+ci7(nci;1thZ%P2&S9:&Bm0rkqo!mK)=.=tl[Ss"n\>+s +If[Ru\1%~> +endstream +endobj +7 0 obj + 58816 +endobj +3 0 obj + << + /Parent null + /Type /Pages + /MediaBox [0.0000 0.0000 731.00 403.00] + /Resources 8 0 R + /Kids [5 0 R] + /Count 1 + >> +endobj +9 0 obj + [/PDF /Text /ImageC] +endobj +10 0 obj + << + /S /Transparency + /CS /DeviceRGB + /I true + /K false + >> +endobj +11 0 obj + << + /Alpha1 + << + /ca 1.0000 + /CA 1.0000 + /BM /Normal + /AIS false + >> + >> +endobj +8 0 obj + << + /ProcSet 9 0 R + /ExtGState 11 0 R + >> +endobj +xref +0 12 +0000000000 65535 f +0000000015 00000 n +0000000315 00000 n +0000059559 00000 n +0000000445 00000 n +0000000521 00000 n +0000000609 00000 n +0000059535 00000 n +0000060013 00000 n +0000059729 00000 n +0000059768 00000 n +0000059870 00000 n +trailer +<< + /Size 12 + /Root 2 0 R + /Info 1 0 R +>> +startxref +60086 +%%EOF diff --git a/images/sat-rs-structure/satrs-structure.graphml b/images/satrs-structure/satrs-structure.graphml similarity index 100% rename from images/sat-rs-structure/satrs-structure.graphml rename to images/satrs-structure/satrs-structure.graphml diff --git a/images/sat-rs-structure/satrs-structure.pdf b/images/satrs-structure/satrs-structure.pdf similarity index 100% rename from images/sat-rs-structure/satrs-structure.pdf rename to images/satrs-structure/satrs-structure.pdf diff --git a/satrs-book/book.toml b/satrs-book/book.toml index 8d01bb6..7d56896 100644 --- a/satrs-book/book.toml +++ b/satrs-book/book.toml @@ -4,3 +4,6 @@ language = "en" multilingual = false src = "src" title = "The sat-rs book" + +[output.html] +[output.linkcheck] diff --git a/satrs-book/src/communication.md b/satrs-book/src/communication.md index 8e8acd7..4976d7b 100644 --- a/satrs-book/src/communication.md +++ b/satrs-book/src/communication.md @@ -1,3 +1,5 @@ +

+ # Communication with sat-rs based software Communication is a vital topic for remote system which are usually not (directly) @@ -15,10 +17,16 @@ it is still centered around small packets. `sat-rs` provides support for these E standards and also attempts to fill the gap to the internet protocol by providing the following components. -1. [UDP TMTC Server](https://docs.rs/satrs-core/0.1.0-alpha.0/satrs_core/hal/host/udp_server/index.html#). +1. [UDP TMTC Server](https://docs.rs/satrs-core/0.1.0-alpha.0/satrs_core/hal/host/udp_server/index.html). UDP is already packet based which makes it an excellent fit for exchanging space packets. -2. TCP TMTC Server. This is a stream based protocol, so the server uses the COBS framing protocol - to always deliver complete packets. +2. [TCP TMTC Server Components](https://docs.rs/satrs-core/0.1.0-alpha.1/satrs_core/hal/std/tcp_server/index.html). + TCP is a stream based protocol, so the framework provides building blocks to parse telemetry + from an arbitrary bytestream. Two concrete implementations are provided: + - [TCP spacepackets server](https://docs.rs/satrs-core/0.1.0-alpha.1/satrs_core/hal/std/tcp_server/struct.TcpSpacepacketsServer.html) + to parse tightly packed CCSDS Spacepackets. + - [TCP COBS server](https://docs.rs/satrs-core/0.1.0-alpha.1/satrs_core/hal/std/tcp_server/struct.TcpTmtcInCobsServer.html) + to parse generic frames wrapped with the + [COBS protocol](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing). # Working with telemetry and telecommands (TMTC) diff --git a/satrs-book/src/constrained-systems.md b/satrs-book/src/constrained-systems.md index 4dbdb7a..3580df7 100644 --- a/satrs-book/src/constrained-systems.md +++ b/satrs-book/src/constrained-systems.md @@ -18,7 +18,7 @@ running out of memory (something even Rust can not protect from) or heap fragmen A huge candidate for heap allocations is the TMTC and handling. TC, TMs and IPC data are all candidates where the data size might vary greatly. The regular solution for host systems might be to send around this data as a `Vec` until it is dropped. `sat-rs` provides -another solution to avoid run-time allocations by offering and recommendng pre-allocated static +another solution to avoid run-time allocations by offering pre-allocated static pools. These pools are split into subpools where each subpool can have different page sizes. diff --git a/satrs-book/src/example.md b/satrs-book/src/example.md index db49cac..9152a18 100644 --- a/satrs-book/src/example.md +++ b/satrs-book/src/example.md @@ -9,22 +9,144 @@ software application. ## Structure of the example project The example project contains components which could also be expected to be part of a production -On-Board Software. +On-Board Software. A structural diagram of the example application is given to provide +a brief high-level view of the components used inside the example application: -1. A UDP and TCP server to receive telecommands and poll telemetry from. This might be an optional - component for an OBSW which is only used during the development phase on ground. The TCP - server parses space packets by using the CCSDS space packet ID as the packet start delimiter. -2. A PUS service stack which exposes some functionality conformant with the ECSS PUS service. This - currently includes the following services: - - Service 1 for telecommand verification. - - Service 3 for housekeeping telemetry handling. - - Service 5 for management and downlink of on-board events. - - Service 8 for handling on-board actions. - - Service 11 for scheduling telecommands to be released at a specific time. - - Service 17 for test purposes (pings) -3. An event manager component which handles the event IPC mechanism. -4. A TC source component which demultiplexes and routes telecommands based on parameters like - packet APID or PUS service and subservice type. -5. A TM sink sink component which is the target of all sent telemetry and sends it to downlink +![satrs-example component structure](images/satrs-example/satrs-example-structure.png) + +The dotted lines are used to denote optional components. In this case, the static pool components +are optional because the heap can be used as a simpler mechanism to store TMTC packets as well. +Some additional explanation is provided for the various components. + +### TCP/IP server components + +The example includes a UDP and TCP server to receive telecommands and poll telemetry from. This +might be an optional component for an OBSW which is only used during the development phase on +ground. The UDP server is strongly based on the +[UDP TC server](https://docs.rs/satrs-core/0.1.0-alpha.1/satrs_core/hal/std/udp_server/struct.UdpTcServer.html). +This server component is wrapped by a TMTC server which handles all telemetry to the last connected +client. + +The TCP server is based on the [TCP Spacepacket Server](https://docs.rs/satrs-core/0.1.0-alpha.1/satrs_core/hal/std/tcp_server/struct.TcpSpacepacketsServer.html) +class. It parses space packets by using the CCSDS space packet ID as the packet +start delimiter. All available telemetry will be sent back to a client after having read all +telecommands from the client. + +### TMTC Infrastructure + +The most important components of the TMTC infrastructure include the following components: + +- A TC source component which demultiplexes and routes telecommands based on parameters like + packet APID or PUS service and subservice type. +- A TM sink sink component which is the target of all sent telemetry and sends it to downlink handlers like the UDP and TCP server. -6. An AOCS example task which can also process some PUS commands. + +You can read the [Communications chapter](./communication.md) for more +background information on the chosen TMTC infrastructure approach. + +### PUS Service Components + +A PUS service stack is provided which exposes some functionality conformant with the ECSS PUS +services. This currently includes the following services: + +- Service 1 for telecommand verification. The verification handling is handled locally: Each + component which generates verification telemetry in some shape or form receives a + [reporter](https://docs.rs/satrs-core/0.1.0-alpha.1/satrs_core/pus/verification/struct.VerificationReporterWithSender.html) + object which can be used to send PUS 1 verification telemetry to the TM funnel. +- Service 3 for housekeeping telemetry handling. +- Service 5 for management and downlink of on-board events. +- Service 8 for handling on-board actions. +- Service 11 for scheduling telecommands to be released at a specific time. This component + uses the [PUS scheduler class](https://docs.rs/satrs-core/0.1.0-alpha.1/satrs_core/pus/scheduler/alloc_mod/struct.PusScheduler.html) + which performs the core logic of scheduling telecommands. All telecommands released by the + scheduler are sent to the central TC source using a message. +- Service 17 for test purposes like pings. + +### Event Management Component + +An event manager based on the sat-rs +[event manager component](https://docs.rs/satrs-core/0.1.0-alpha.1/satrs_core/event_man/index.html) +is provided to handle the event IPC and FDIR mechanism. The event message are converted to PUS 5 +telemetry by the +[PUS event dispatcher](https://docs.rs/satrs-core/0.1.0-alpha.1/satrs_core/pus/event_man/alloc_mod/struct.PusEventDispatcher.html). + +You can read the [events](./events.md) chapter for more in-depth information about event management. + +### Sample Application Components + +These components are example mission specific. They provide an idea how mission specific modules +would look like the sat-rs context. It currently includes the following components: + +- An Attitute and Orbit Control (AOCS) example task which can also process some PUS commands. + +## Dataflow + +The interaction of the various components is provided in the following diagram: + +![satrs-example dataflow diagram](images/satrs-example/satrs-example-dataflow.png) + +It should be noted that an arrow coming out of a component group refers to multiple components +in that group. An explanation for important component groups will be given. + +#### TMTC component group + +This groups is the primary interface for clients to communicate with the on-board software +using a standardized TMTC protocol. The example uses the +[ECSS PUS protocol](https://ecss.nl/standard/ecss-e-st-70-41c-space-engineering-telemetry-and-telecommand-packet-utilization-15-april-2016/). +In the future, this might be extended with the +[CCSDS File Delivery Protocol](https://public.ccsds.org/Pubs/727x0b5.pdf). + +A client can connect to the UDP or TCP server to send these PUS packets to the on-board software. +These servers then forward the telecommads to a centralized TC source component using a dedicated +message abstraction. + +This TC source component then demultiplexes the message and forwards it to the relevant components. +Right now, it forwards all PUS requests to the respective PUS service handlers using the PUS +receiver component. The individual PUS services are running in a separate thread. In the future, +additional forwarding to components like a CFDP handler might be added as well. It should be noted +that PUS11 commands might contain other PUS commands which should be scheduled in the future. +These wrapped commands are forwarded to the PUS11 handler. When the schedule releases those +commands, it forwards the released commands to the TC source again. This allows the scheduler +and the TC source to run in separate threads and keeps them cleanly separated. + +All telemetry generated by the on-board software is sent to a centralized TM funnel. This component +also performs a demultiplexing step to forward all telemetry to the relevant TM recipients. +In the example case, this is the last UDP client, or a connected TCP client. In the future, +forwarding to a persistent telemetry store and a simulated communication component might be +added here as well. The centralized TM funnel also takes care of some packet processing steps which +need to be applied for each ECSS PUS packet, for example CCSDS specific APID incrementation and +PUS specific message counter incrementation. + +#### Application Group + +The application components generally do not receive raw PUS packets directly, even though +this is certainly possible. Instead, they receive internalized messages from the PUS service +handlers. For example, instead of receiving a PUS 8 Action Telecommand directly, an application +component will receive a special `ActionRequest` message type reduced to the basic important +information required to execute a request. These special requests are denoted by the blue arrow +in the diagram. + +It should be noted that the arrow pointing towards the event manager points in both directions. +This is because the application components might be interested in events generated by other +components as well. This mechanism is oftentimes used to implement the FDIR functionality on system +and component level. + +#### Shared components and functional interfaces + +It should be noted that sometimes, a functional interface is used instead of a message. This +is used for the generation of verification telemetry. The verification reporter is a clonable +component which generates and sends PUS1 verification telemetry directly to the TM funnel. This +introduces a loose coupling to the PUS standard but was considered the easiest solution for +a project which utilizes PUS as the main communication protocol. In the future, a generic +verification abstraction might be introduced to completely decouple the application layer from +PUS. + +The same concept is applied if the backing store of TMTC packets are shared pools. Every +component which needs to read telecommands inside that shared pool or generate new telemetry +into that shared pool will received a clonable shared handle to that pool. + +The same concept could be extended to power or thermal handling. For example, a shared power helper +component might be used to retrieve power state information and send power switch commands through +a functional interface. The actual implementation of the functional interface might still use +shared memory and/or messages, but the functional interface makes using and testing the interaction +with these components easier. diff --git a/satrs-book/src/images/satrs-example/satrs-example-dataflow.png b/satrs-book/src/images/satrs-example/satrs-example-dataflow.png new file mode 100644 index 0000000..4ca3b5d Binary files /dev/null and b/satrs-book/src/images/satrs-example/satrs-example-dataflow.png differ diff --git a/satrs-book/src/images/satrs-example/satrs-example-structure.png b/satrs-book/src/images/satrs-example/satrs-example-structure.png new file mode 100644 index 0000000..abeebb9 Binary files /dev/null and b/satrs-book/src/images/satrs-example/satrs-example-structure.png differ diff --git a/satrs-core/src/pus/mod.rs b/satrs-core/src/pus/mod.rs index 5c62375..64a78ce 100644 --- a/satrs-core/src/pus/mod.rs +++ b/satrs-core/src/pus/mod.rs @@ -399,7 +399,7 @@ pub mod std_mod { EcssTmSenderCore, EcssTmtcError, GenericRecvError, GenericSendError, PusTmWrapper, TryRecvTmtcError, }; - use crate::tmtc::tm_helper::SharedTmStore; + use crate::tmtc::tm_helper::SharedTmPool; use crate::ChannelId; use alloc::boxed::Box; use alloc::vec::Vec; @@ -441,14 +441,14 @@ pub mod std_mod { } #[derive(Clone)] - pub struct MpscTmInStoreSender { + pub struct MpscTmInSharedPoolSender { id: ChannelId, name: &'static str, - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, sender: mpsc::Sender, } - impl EcssChannel for MpscTmInStoreSender { + impl EcssChannel for MpscTmInSharedPoolSender { fn id(&self) -> ChannelId { self.id } @@ -458,7 +458,7 @@ pub mod std_mod { } } - impl MpscTmInStoreSender { + impl MpscTmInSharedPoolSender { pub fn send_direct_tm(&self, tm: PusTmCreator) -> Result<(), EcssTmtcError> { let addr = self.shared_tm_store.add_pus_tm(&tm)?; self.sender @@ -467,7 +467,7 @@ pub mod std_mod { } } - impl EcssTmSenderCore for MpscTmInStoreSender { + impl EcssTmSenderCore for MpscTmInSharedPoolSender { fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> { match tm { PusTmWrapper::InStore(addr) => { @@ -479,11 +479,11 @@ pub mod std_mod { } } - impl MpscTmInStoreSender { + impl MpscTmInSharedPoolSender { pub fn new( id: ChannelId, name: &'static str, - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, sender: mpsc::Sender, ) -> Self { Self { @@ -582,7 +582,7 @@ pub mod std_mod { pub struct CrossbeamTmInStoreSender { id: ChannelId, name: &'static str, - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, sender: crossbeam_channel::Sender, } @@ -590,7 +590,7 @@ pub mod std_mod { pub fn new( id: ChannelId, name: &'static str, - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, sender: crossbeam_channel::Sender, ) -> Self { Self { @@ -951,15 +951,15 @@ pub mod tests { StoreAddr, }; use crate::pus::verification::RequestId; - use crate::tmtc::tm_helper::SharedTmStore; + use crate::tmtc::tm_helper::SharedTmPool; use super::verification::{ TcStateAccepted, VerificationReporterCfg, VerificationReporterWithSender, VerificationToken, }; use super::{ EcssTcAndToken, EcssTcInSharedStoreConverter, EcssTcInVecConverter, MpscTcReceiver, - MpscTmAsVecSender, MpscTmInStoreSender, PusPacketHandlerResult, PusPacketHandlingError, - PusServiceHelper, TcInMemory, + MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, + PusPacketHandlingError, PusServiceHelper, TcInMemory, }; pub const TEST_APID: u16 = 0x101; @@ -1003,7 +1003,7 @@ pub mod tests { pus_buf: [u8; 2048], tm_buf: [u8; 2048], tc_pool: SharedStaticMemoryPool, - tm_pool: SharedTmStore, + tm_pool: SharedTmPool, tc_sender: mpsc::Sender, tm_receiver: mpsc::Receiver, verification_handler: VerificationReporterWithSender, @@ -1019,17 +1019,21 @@ pub mod tests { let tc_pool = StaticMemoryPool::new(pool_cfg.clone()); let tm_pool = StaticMemoryPool::new(pool_cfg); let shared_tc_pool = SharedStaticMemoryPool::new(RwLock::new(tc_pool)); - let shared_tm_pool = SharedTmStore::new(tm_pool); + let shared_tm_pool = SharedTmPool::new(tm_pool); let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel(); let (tm_tx, tm_rx) = mpsc::channel(); - let verif_sender = - MpscTmInStoreSender::new(0, "verif_sender", shared_tm_pool.clone(), tm_tx.clone()); + let verif_sender = MpscTmInSharedPoolSender::new( + 0, + "verif_sender", + shared_tm_pool.clone(), + tm_tx.clone(), + ); let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); let verification_handler = VerificationReporterWithSender::new(&verif_cfg, Box::new(verif_sender)); let test_srv_tm_sender = - MpscTmInStoreSender::new(0, "TEST_SENDER", shared_tm_pool.clone(), tm_tx); + MpscTmInSharedPoolSender::new(0, "TEST_SENDER", shared_tm_pool.clone(), tm_tx); let test_srv_tc_receiver = MpscTcReceiver::new(0, "TEST_RECEIVER", test_srv_tc_rx); let in_store_converter = EcssTcInSharedStoreConverter::new(shared_tc_pool.clone(), 2048); @@ -1073,7 +1077,7 @@ pub mod tests { let next_msg = self.tm_receiver.try_recv(); assert!(next_msg.is_ok()); let tm_addr = next_msg.unwrap(); - let tm_pool = self.tm_pool.shared_pool.read().unwrap(); + let tm_pool = self.tm_pool.0.read().unwrap(); let tm_raw = tm_pool.read(&tm_addr).unwrap(); self.tm_buf[0..tm_raw.len()].copy_from_slice(tm_raw); PusTmReader::new(&self.tm_buf, 7).unwrap().0 @@ -1091,7 +1095,7 @@ pub mod tests { let next_msg = self.tm_receiver.try_recv(); assert!(next_msg.is_ok()); let tm_addr = next_msg.unwrap(); - let tm_pool = self.tm_pool.shared_pool.read().unwrap(); + let tm_pool = self.tm_pool.0.read().unwrap(); let tm_raw = tm_pool.read(&tm_addr).unwrap(); let tm = PusTmReader::new(tm_raw, 7).unwrap().0; assert_eq!(PusPacket::service(&tm), 1); diff --git a/satrs-core/src/pus/verification.rs b/satrs-core/src/pus/verification.rs index 6407bf3..ca7c272 100644 --- a/satrs-core/src/pus/verification.rs +++ b/satrs-core/src/pus/verification.rs @@ -18,8 +18,8 @@ //! use satrs_core::pool::{PoolProviderMemInPlaceWithGuards, StaticMemoryPool, StaticPoolConfig}; //! use satrs_core::pus::verification::{VerificationReporterCfg, VerificationReporterWithSender}; //! use satrs_core::seq_count::SeqCountProviderSimple; -//! use satrs_core::pus::MpscTmInStoreSender; -//! use satrs_core::tmtc::tm_helper::SharedTmStore; +//! use satrs_core::pus::MpscTmInSharedPoolSender; +//! use satrs_core::tmtc::tm_helper::SharedTmPool; //! use spacepackets::ecss::PusPacket; //! use spacepackets::SpHeader; //! use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader}; @@ -30,10 +30,10 @@ //! //! let pool_cfg = StaticPoolConfig::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)]); //! let tm_pool = StaticMemoryPool::new(pool_cfg.clone()); -//! let shared_tm_store = SharedTmStore::new(tm_pool); +//! let shared_tm_store = SharedTmPool::new(tm_pool); //! let tm_store = shared_tm_store.clone_backing_pool(); //! let (verif_tx, verif_rx) = mpsc::channel(); -//! let sender = MpscTmInStoreSender::new(0, "Test Sender", shared_tm_store, verif_tx); +//! let sender = MpscTmInSharedPoolSender::new(0, "Test Sender", shared_tm_store, verif_tx); //! let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); //! let mut reporter = VerificationReporterWithSender::new(&cfg , Box::new(sender)); //! @@ -1332,8 +1332,8 @@ mod tests { VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender, VerificationToken, }; - use crate::pus::{EcssChannel, MpscTmInStoreSender, PusTmWrapper}; - use crate::tmtc::tm_helper::SharedTmStore; + use crate::pus::{EcssChannel, MpscTmInSharedPoolSender, PusTmWrapper}; + use crate::tmtc::tm_helper::SharedTmPool; use crate::ChannelId; use alloc::boxed::Box; use alloc::format; @@ -1487,9 +1487,10 @@ mod tests { #[test] fn test_mpsc_verif_send_sync() { let pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(8, 8)])); - let shared_tm_store = SharedTmStore::new(pool); + let shared_tm_store = SharedTmPool::new(pool); let (tx, _) = mpsc::channel(); - let mpsc_verif_sender = MpscTmInStoreSender::new(0, "verif_sender", shared_tm_store, tx); + let mpsc_verif_sender = + MpscTmInSharedPoolSender::new(0, "verif_sender", shared_tm_store, tx); is_send(&mpsc_verif_sender); } @@ -2142,10 +2143,11 @@ mod tests { fn test_seq_count_increment() { let pool_cfg = StaticPoolConfig::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)]); let tm_pool = StaticMemoryPool::new(pool_cfg.clone()); - let shared_tm_store = SharedTmStore::new(tm_pool); + let shared_tm_store = SharedTmPool::new(tm_pool); let shared_tm_pool = shared_tm_store.clone_backing_pool(); let (verif_tx, verif_rx) = mpsc::channel(); - let sender = MpscTmInStoreSender::new(0, "Verification Sender", shared_tm_store, verif_tx); + let sender = + MpscTmInSharedPoolSender::new(0, "Verification Sender", shared_tm_store, verif_tx); let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); let mut reporter = VerificationReporterWithSender::new(&cfg, Box::new(sender)); diff --git a/satrs-core/src/tmtc/tm_helper.rs b/satrs-core/src/tmtc/tm_helper.rs index fc0a8e9..c8a09a3 100644 --- a/satrs-core/src/tmtc/tm_helper.rs +++ b/satrs-core/src/tmtc/tm_helper.rs @@ -17,26 +17,26 @@ pub mod std_mod { use std::sync::{Arc, RwLock}; #[derive(Clone)] - pub struct SharedTmStore { - pub shared_pool: SharedStaticMemoryPool, - } + pub struct SharedTmPool(pub SharedStaticMemoryPool); - impl SharedTmStore { + impl SharedTmPool { pub fn new(shared_pool: StaticMemoryPool) -> Self { - Self { - shared_pool: Arc::new(RwLock::new(shared_pool)), - } + Self(Arc::new(RwLock::new(shared_pool))) } pub fn clone_backing_pool(&self) -> SharedStaticMemoryPool { - self.shared_pool.clone() + self.0.clone() + } + pub fn shared_pool(&self) -> &SharedStaticMemoryPool { + &self.0 + } + + pub fn shared_pool_mut(&mut self) -> &mut SharedStaticMemoryPool { + &mut self.0 } pub fn add_pus_tm(&self, pus_tm: &PusTmCreator) -> Result { - let mut pg = self - .shared_pool - .write() - .map_err(|_| EcssTmtcError::StoreLock)?; + let mut pg = self.0.write().map_err(|_| EcssTmtcError::StoreLock)?; let (addr, buf) = pg.free_element(pus_tm.len_written())?; pus_tm .write_to_bytes(buf) diff --git a/satrs-core/tests/pus_verification.rs b/satrs-core/tests/pus_verification.rs index a62b7a5..557a8b2 100644 --- a/satrs-core/tests/pus_verification.rs +++ b/satrs-core/tests/pus_verification.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "crossbeam")] +//#[cfg(feature = "crossbeam")] pub mod crossbeam_test { use hashbrown::HashMap; use satrs_core::pool::{ @@ -9,7 +9,7 @@ pub mod crossbeam_test { FailParams, RequestId, VerificationReporterCfg, VerificationReporterWithSender, }; use satrs_core::pus::CrossbeamTmInStoreSender; - use satrs_core::tmtc::tm_helper::SharedTmStore; + use satrs_core::tmtc::tm_helper::SharedTmPool; use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader}; use spacepackets::ecss::tm::PusTmReader; use spacepackets::ecss::{EcssEnumU16, EcssEnumU8, PusPacket, WritablePusPacket}; @@ -37,12 +37,12 @@ pub mod crossbeam_test { let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap(); // Shared pool object to store the verification PUS telemetry let pool_cfg = StaticPoolConfig::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)]); - let shared_tm_store = SharedTmStore::new(StaticMemoryPool::new(pool_cfg.clone())); + let shared_tm_pool = SharedTmPool::new(StaticMemoryPool::new(pool_cfg.clone())); let shared_tc_pool_0 = Arc::new(RwLock::new(StaticMemoryPool::new(pool_cfg))); let shared_tc_pool_1 = shared_tc_pool_0.clone(); let (tx, rx) = crossbeam_channel::bounded(10); let sender = - CrossbeamTmInStoreSender::new(0, "verif_sender", shared_tm_store.clone(), tx.clone()); + CrossbeamTmInStoreSender::new(0, "verif_sender", shared_tm_pool.clone(), tx.clone()); let mut reporter_with_sender_0 = VerificationReporterWithSender::new(&cfg, Box::new(sender)); let mut reporter_with_sender_1 = reporter_with_sender_0.clone(); @@ -145,7 +145,7 @@ pub mod crossbeam_test { .recv_timeout(Duration::from_millis(50)) .expect("Packet reception timeout"); let tm_len; - let shared_tm_store = shared_tm_store.clone_backing_pool(); + let shared_tm_store = shared_tm_pool.clone_backing_pool(); { let mut rg = shared_tm_store.write().expect("Error locking shared pool"); let store_guard = rg.read_with_guard(verif_addr); diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 113103c..71774ce 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -17,6 +17,7 @@ use log::info; use pus::test::create_test_service_dynamic; use satrs_core::hal::std::tcp_server::ServerConfig; use satrs_core::hal::std::udp_server::UdpTcServer; +use satrs_core::tmtc::tm_helper::SharedTmPool; use satrs_example::config::pool::{create_sched_tc_pool, create_static_pools}; use satrs_example::config::tasks::{ FREQ_MS_AOCS, FREQ_MS_EVENT_HANDLING, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC, @@ -37,14 +38,13 @@ use crate::pus::{PusReceiver, PusTcMpscRouter}; use crate::requests::RequestWithToken; use crate::tcp::{SyncTcpTmSource, TcpTask}; use crate::tmtc::{ - PusTcSourceProviderSharedPool, SharedTcPool, TcArgs, TmArgs, TmtcTaskDynamic, TmtcTaskStatic, + PusTcSourceProviderSharedPool, SharedTcPool, TcSourceTaskDynamic, TcSourceTaskStatic, }; use crate::udp::{StaticUdpTmHandler, UdpTmtcServer}; use satrs_core::pus::event_man::EventRequestWithToken; use satrs_core::pus::verification::{VerificationReporterCfg, VerificationReporterWithSender}; -use satrs_core::pus::{EcssTmSender, MpscTmAsVecSender, MpscTmInStoreSender}; +use satrs_core::pus::{EcssTmSender, MpscTmAsVecSender, MpscTmInSharedPoolSender}; use satrs_core::spacepackets::{time::cds::TimeProvider, time::TimeWriter}; -use satrs_core::tmtc::tm_helper::SharedTmStore; use satrs_core::tmtc::{CcsdsDistributor, TargetId}; use satrs_core::ChannelId; use satrs_example::TargetIdWithApid; @@ -65,7 +65,7 @@ fn create_verification_reporter(verif_sender: impl EcssTmSender) -> Verification #[allow(dead_code)] fn static_tmtc_pool_main() { let (tm_pool, tc_pool) = create_static_pools(); - let shared_tm_store = SharedTmStore::new(tm_pool); + let shared_tm_pool = SharedTmPool::new(tm_pool); let shared_tc_pool = SharedTcPool { pool: Arc::new(RwLock::new(tc_pool)), }; @@ -75,10 +75,10 @@ fn static_tmtc_pool_main() { // Every software component which needs to generate verification telemetry, receives a cloned // verification reporter. - let verif_reporter = create_verification_reporter(MpscTmInStoreSender::new( + let verif_reporter = create_verification_reporter(MpscTmInSharedPoolSender::new( TmSenderId::PusVerification as ChannelId, "verif_sender", - shared_tm_store.clone(), + shared_tm_pool.clone(), tm_funnel_tx.clone(), )); @@ -88,22 +88,13 @@ fn static_tmtc_pool_main() { let mut request_map = HashMap::new(); request_map.insert(acs_target_id, acs_thread_tx); - let tc_source_wrapper = PusTcSourceProviderSharedPool { + // This helper structure is used by all telecommand providers which need to send telecommands + // to the TC source. + let tc_source = PusTcSourceProviderSharedPool { shared_pool: shared_tc_pool.clone(), tc_source: tc_source_tx, }; - // Create clones here to allow moving the values - let tc_args = TcArgs { - tc_source: tc_source_wrapper.clone(), - tc_receiver: tc_source_rx, - }; - let tm_args = TmArgs { - tm_store: shared_tm_store.clone(), - tm_sink_sender: tm_funnel_tx.clone(), - tm_udp_server_rx: tm_server_rx, - }; - // Create event handling components // These sender handles are used to send event requests, for example to enable or disable // certain events. @@ -112,10 +103,10 @@ fn static_tmtc_pool_main() { // The event task is the core handler to perform the event routing and TM handling as specified // in the sat-rs documentation. let mut event_handler = EventHandler::new( - MpscTmInStoreSender::new( + MpscTmInSharedPoolSender::new( TmSenderId::AllEvents as ChannelId, "ALL_EVENTS_TX", - shared_tm_store.clone(), + shared_tm_pool.clone(), tm_funnel_tx.clone(), ), verif_reporter.clone(), @@ -135,7 +126,7 @@ fn static_tmtc_pool_main() { action_service_receiver: pus_action_tx, }; let pus_test_service = create_test_service_static( - shared_tm_store.clone(), + shared_tm_pool.clone(), tm_funnel_tx.clone(), verif_reporter.clone(), shared_tc_pool.pool.clone(), @@ -143,15 +134,15 @@ fn static_tmtc_pool_main() { pus_test_rx, ); let pus_scheduler_service = create_scheduler_service_static( - shared_tm_store.clone(), + shared_tm_pool.clone(), tm_funnel_tx.clone(), verif_reporter.clone(), - tc_source_wrapper, + tc_source.clone(), pus_sched_rx, create_sched_tc_pool(), ); let pus_event_service = create_event_service_static( - shared_tm_store.clone(), + shared_tm_pool.clone(), tm_funnel_tx.clone(), verif_reporter.clone(), shared_tc_pool.pool.clone(), @@ -159,7 +150,7 @@ fn static_tmtc_pool_main() { event_request_tx, ); let pus_action_service = create_action_service_static( - shared_tm_store.clone(), + shared_tm_pool.clone(), tm_funnel_tx.clone(), verif_reporter.clone(), shared_tc_pool.pool.clone(), @@ -167,7 +158,7 @@ fn static_tmtc_pool_main() { request_map.clone(), ); let pus_hk_service = create_hk_service_static( - shared_tm_store.clone(), + shared_tm_pool.clone(), tm_funnel_tx.clone(), verif_reporter.clone(), shared_tc_pool.pool.clone(), @@ -182,11 +173,10 @@ fn static_tmtc_pool_main() { pus_test_service, ); - let ccsds_receiver = CcsdsReceiver { - tc_source: tc_args.tc_source.clone(), - }; - let mut tmtc_task = TmtcTaskStatic::new( - tc_args, + let ccsds_receiver = CcsdsReceiver { tc_source }; + let mut tmtc_task = TcSourceTaskStatic::new( + shared_tc_pool.clone(), + tc_source_rx, PusReceiver::new(verif_reporter.clone(), pus_router), ); @@ -197,8 +187,8 @@ fn static_tmtc_pool_main() { let mut udp_tmtc_server = UdpTmtcServer { udp_tc_server, tm_handler: StaticUdpTmHandler { - tm_rx: tm_args.tm_udp_server_rx, - tm_store: tm_args.tm_store.clone_backing_pool(), + tm_rx: tm_server_rx, + tm_store: shared_tm_pool.clone_backing_pool(), }, }; @@ -213,10 +203,10 @@ fn static_tmtc_pool_main() { .expect("tcp server creation failed"); let mut acs_task = AcsTask::new( - MpscTmInStoreSender::new( + MpscTmInSharedPoolSender::new( TmSenderId::AcsSubsystem as ChannelId, "ACS_TASK_SENDER", - shared_tm_store.clone(), + shared_tm_pool.clone(), tm_funnel_tx.clone(), ), acs_thread_rx, @@ -224,7 +214,7 @@ fn static_tmtc_pool_main() { ); let mut tm_funnel = TmFunnelStatic::new( - shared_tm_store, + shared_tm_pool, sync_tm_tcp_source, tm_funnel_rx, tm_server_tx, @@ -399,7 +389,7 @@ fn dyn_tmtc_pool_main() { let ccsds_receiver = CcsdsReceiver { tc_source }; - let mut tmtc_task = TmtcTaskDynamic::new( + let mut tmtc_task = TcSourceTaskDynamic::new( tc_source_rx, PusReceiver::new(verif_reporter.clone(), pus_router), ); diff --git a/satrs-example/src/pus/action.rs b/satrs-example/src/pus/action.rs index 2c7afb2..7c59723 100644 --- a/satrs-example/src/pus/action.rs +++ b/satrs-example/src/pus/action.rs @@ -6,12 +6,12 @@ use satrs_core::pus::verification::{ }; use satrs_core::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - EcssTcReceiver, EcssTmSender, MpscTcReceiver, MpscTmAsVecSender, MpscTmInStoreSender, + EcssTcReceiver, EcssTmSender, MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase, PusServiceHelper, }; use satrs_core::spacepackets::ecss::tc::PusTcReader; use satrs_core::spacepackets::ecss::PusPacket; -use satrs_core::tmtc::tm_helper::SharedTmStore; +use satrs_core::tmtc::tm_helper::SharedTmPool; use satrs_core::ChannelId; use satrs_example::config::{tmtc_err, TcReceiverId, TmSenderId, PUS_APID}; use satrs_example::TargetIdWithApid; @@ -19,14 +19,14 @@ use std::collections::HashMap; use std::sync::mpsc::{self, Sender}; pub fn create_action_service_static( - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, tm_funnel_tx: mpsc::Sender, verif_reporter: VerificationReporterWithSender, tc_pool: SharedStaticMemoryPool, pus_action_rx: mpsc::Receiver, request_map: HashMap>, ) -> Pus8Wrapper { - let action_srv_tm_sender = MpscTmInStoreSender::new( + let action_srv_tm_sender = MpscTmInSharedPoolSender::new( TmSenderId::PusAction as ChannelId, "PUS_8_TM_SENDER", shared_tm_store.clone(), diff --git a/satrs-example/src/pus/event.rs b/satrs-example/src/pus/event.rs index 825c6fd..fbbe942 100644 --- a/satrs-example/src/pus/event.rs +++ b/satrs-example/src/pus/event.rs @@ -7,22 +7,22 @@ use satrs_core::pus::event_srv::PusService5EventHandler; use satrs_core::pus::verification::VerificationReporterWithSender; use satrs_core::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - MpscTcReceiver, MpscTmAsVecSender, MpscTmInStoreSender, PusPacketHandlerResult, + MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, PusServiceHelper, }; -use satrs_core::tmtc::tm_helper::SharedTmStore; +use satrs_core::tmtc::tm_helper::SharedTmPool; use satrs_core::ChannelId; use satrs_example::config::{TcReceiverId, TmSenderId, PUS_APID}; pub fn create_event_service_static( - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, tm_funnel_tx: mpsc::Sender, verif_reporter: VerificationReporterWithSender, tc_pool: SharedStaticMemoryPool, pus_event_rx: mpsc::Receiver, event_request_tx: mpsc::Sender, ) -> Pus5Wrapper { - let event_srv_tm_sender = MpscTmInStoreSender::new( + let event_srv_tm_sender = MpscTmInSharedPoolSender::new( TmSenderId::PusEvent as ChannelId, "PUS_5_TM_SENDER", shared_tm_store.clone(), diff --git a/satrs-example/src/pus/hk.rs b/satrs-example/src/pus/hk.rs index a40fd7a..5a27e9f 100644 --- a/satrs-example/src/pus/hk.rs +++ b/satrs-example/src/pus/hk.rs @@ -7,11 +7,11 @@ use satrs_core::pus::verification::{ }; use satrs_core::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - EcssTcReceiver, EcssTmSender, MpscTcReceiver, MpscTmAsVecSender, MpscTmInStoreSender, + EcssTcReceiver, EcssTmSender, MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, PusPacketHandlingError, PusServiceBase, PusServiceHelper, }; use satrs_core::spacepackets::ecss::{hk, PusPacket}; -use satrs_core::tmtc::tm_helper::SharedTmStore; +use satrs_core::tmtc::tm_helper::SharedTmPool; use satrs_core::ChannelId; use satrs_example::config::{hk_err, tmtc_err, TcReceiverId, TmSenderId, PUS_APID}; use satrs_example::TargetIdWithApid; @@ -19,14 +19,14 @@ use std::collections::HashMap; use std::sync::mpsc::{self, Sender}; pub fn create_hk_service_static( - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, tm_funnel_tx: mpsc::Sender, verif_reporter: VerificationReporterWithSender, tc_pool: SharedStaticMemoryPool, pus_hk_rx: mpsc::Receiver, request_map: HashMap>, ) -> Pus3Wrapper { - let hk_srv_tm_sender = MpscTmInStoreSender::new( + let hk_srv_tm_sender = MpscTmInSharedPoolSender::new( TmSenderId::PusHk as ChannelId, "PUS_3_TM_SENDER", shared_tm_store.clone(), diff --git a/satrs-example/src/pus/scheduler.rs b/satrs-example/src/pus/scheduler.rs index 04d8d7a..0842904 100644 --- a/satrs-example/src/pus/scheduler.rs +++ b/satrs-example/src/pus/scheduler.rs @@ -8,10 +8,10 @@ use satrs_core::pus::scheduler_srv::PusService11SchedHandler; use satrs_core::pus::verification::VerificationReporterWithSender; use satrs_core::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, - MpscTcReceiver, MpscTmAsVecSender, MpscTmInStoreSender, PusPacketHandlerResult, + MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSender, PusPacketHandlerResult, PusServiceHelper, }; -use satrs_core::tmtc::tm_helper::SharedTmStore; +use satrs_core::tmtc::tm_helper::SharedTmPool; use satrs_core::ChannelId; use satrs_example::config::{TcReceiverId, TmSenderId, PUS_APID}; @@ -103,14 +103,14 @@ impl Pus11Wrapper { } pub fn create_scheduler_service_static( - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, tm_funnel_tx: mpsc::Sender, verif_reporter: VerificationReporterWithSender, tc_releaser: PusTcSourceProviderSharedPool, pus_sched_rx: mpsc::Receiver, sched_tc_pool: StaticMemoryPool, ) -> Pus11Wrapper { - let sched_srv_tm_sender = MpscTmInStoreSender::new( + let sched_srv_tm_sender = MpscTmInSharedPoolSender::new( TmSenderId::PusSched as ChannelId, "PUS_11_TM_SENDER", shared_tm_store.clone(), diff --git a/satrs-example/src/pus/test.rs b/satrs-example/src/pus/test.rs index b00899c..1958055 100644 --- a/satrs-example/src/pus/test.rs +++ b/satrs-example/src/pus/test.rs @@ -5,27 +5,27 @@ use satrs_core::pus::test::PusService17TestHandler; use satrs_core::pus::verification::{FailParams, VerificationReporterWithSender}; use satrs_core::pus::{ EcssTcAndToken, EcssTcInMemConverter, EcssTcInVecConverter, MpscTcReceiver, MpscTmAsVecSender, - MpscTmInStoreSender, PusPacketHandlerResult, PusServiceHelper, + MpscTmInSharedPoolSender, PusPacketHandlerResult, PusServiceHelper, }; use satrs_core::spacepackets::ecss::tc::PusTcReader; use satrs_core::spacepackets::ecss::PusPacket; use satrs_core::spacepackets::time::cds::TimeProvider; use satrs_core::spacepackets::time::TimeWriter; -use satrs_core::tmtc::tm_helper::SharedTmStore; +use satrs_core::tmtc::tm_helper::SharedTmPool; use satrs_core::ChannelId; use satrs_core::{events::EventU32, pus::EcssTcInSharedStoreConverter}; use satrs_example::config::{tmtc_err, TcReceiverId, TmSenderId, PUS_APID, TEST_EVENT}; use std::sync::mpsc::{self, Sender}; pub fn create_test_service_static( - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, tm_funnel_tx: mpsc::Sender, verif_reporter: VerificationReporterWithSender, tc_pool: SharedStaticMemoryPool, event_sender: mpsc::Sender<(EventU32, Option)>, pus_test_rx: mpsc::Receiver, ) -> Service17CustomWrapper { - let test_srv_tm_sender = MpscTmInStoreSender::new( + let test_srv_tm_sender = MpscTmInSharedPoolSender::new( TmSenderId::PusTest as ChannelId, "PUS_17_TM_SENDER", shared_tm_store.clone(), diff --git a/satrs-example/src/tcp.rs b/satrs-example/src/tcp.rs index c0934e0..b9f3052 100644 --- a/satrs-example/src/tcp.rs +++ b/satrs-example/src/tcp.rs @@ -76,7 +76,6 @@ pub struct TcpTask { SyncTcpTmSource, CcsdsDistributor, >, - phantom: std::marker::PhantomData, } impl TcpTask { @@ -92,7 +91,6 @@ impl TcpTask { tc_receiver, Box::new(PACKET_ID_LOOKUP), )?, - phantom: std::marker::PhantomData, }) } diff --git a/satrs-example/src/tm_funnel.rs b/satrs-example/src/tm_funnel.rs index ba1ff32..9069d72 100644 --- a/satrs-example/src/tm_funnel.rs +++ b/satrs-example/src/tm_funnel.rs @@ -11,7 +11,7 @@ use satrs_core::{ time::cds::MIN_CDS_FIELD_LEN, CcsdsPacket, }, - tmtc::tm_helper::SharedTmStore, + tmtc::tm_helper::SharedTmPool, }; use crate::tcp::SyncTcpTmSource; @@ -70,14 +70,14 @@ impl TmFunnelCommon { pub struct TmFunnelStatic { common: TmFunnelCommon, - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, tm_funnel_rx: Receiver, tm_server_tx: Sender, } impl TmFunnelStatic { pub fn new( - shared_tm_store: SharedTmStore, + shared_tm_store: SharedTmPool, sync_tm_tcp_source: SyncTcpTmSource, tm_funnel_rx: Receiver, tm_server_tx: Sender, diff --git a/satrs-example/src/tmtc.rs b/satrs-example/src/tmtc.rs index 39b4b3c..d173ac7 100644 --- a/satrs-example/src/tmtc.rs +++ b/satrs-example/src/tmtc.rs @@ -8,27 +8,8 @@ use crate::pus::PusReceiver; use satrs_core::pool::{PoolProviderMemInPlace, SharedStaticMemoryPool, StoreAddr, StoreError}; use satrs_core::spacepackets::ecss::tc::PusTcReader; use satrs_core::spacepackets::ecss::PusPacket; -use satrs_core::tmtc::tm_helper::SharedTmStore; use satrs_core::tmtc::ReceivesCcsdsTc; -pub struct TmArgs { - pub tm_store: SharedTmStore, - pub tm_sink_sender: Sender, - pub tm_udp_server_rx: Receiver, -} - -pub struct TcArgs { - pub tc_source: PusTcSourceProviderSharedPool, - pub tc_receiver: Receiver, -} - -impl TcArgs { - #[allow(dead_code)] - fn split(self) -> (PusTcSourceProviderSharedPool, Receiver) { - (self.tc_source, self.tc_receiver) - } -} - #[derive(Debug, Clone, PartialEq, Eq, Error)] pub enum MpscStoreAndSendError { #[error("Store error: {0}")] @@ -110,16 +91,23 @@ impl ReceivesCcsdsTc for PusTcSourceProviderDynamic { } } -pub struct TmtcTaskStatic { - tc_args: TcArgs, +// TC source components where static pools are the backing memory of the received telecommands. +pub struct TcSourceTaskStatic { + shared_tc_pool: SharedTcPool, + tc_receiver: Receiver, tc_buf: [u8; 4096], pus_receiver: PusReceiver, } -impl TmtcTaskStatic { - pub fn new(tc_args: TcArgs, pus_receiver: PusReceiver) -> Self { +impl TcSourceTaskStatic { + pub fn new( + shared_tc_pool: SharedTcPool, + tc_receiver: Receiver, + pus_receiver: PusReceiver, + ) -> Self { Self { - tc_args, + shared_tc_pool, + tc_receiver, tc_buf: [0; 4096], pus_receiver, } @@ -130,12 +118,10 @@ impl TmtcTaskStatic { } pub fn poll_tc(&mut self) -> bool { - match self.tc_args.tc_receiver.try_recv() { + match self.tc_receiver.try_recv() { Ok(addr) => { let pool = self - .tc_args - .tc_source - .shared_pool + .shared_tc_pool .pool .read() .expect("locking tc pool failed"); @@ -171,12 +157,13 @@ impl TmtcTaskStatic { } } -pub struct TmtcTaskDynamic { +// TC source components where the heap is the backing memory of the received telecommands. +pub struct TcSourceTaskDynamic { pub tc_receiver: Receiver>, pus_receiver: PusReceiver, } -impl TmtcTaskDynamic { +impl TcSourceTaskDynamic { pub fn new(tc_receiver: Receiver>, pus_receiver: PusReceiver) -> Self { Self { tc_receiver,