From 1fc07e742fa7322be55f6a10b502de44de32b39a Mon Sep 17 00:00:00 2001 From: Duke <40759437+dukesteen@users.noreply.github.com> Date: Wed, 2 Mar 2022 20:08:51 +0100 Subject: [PATCH] Guides for Serilog and EFCore (#2134) * Add serilog guide * added suggestions from Rozen * Add efcore guide * Fix review changes * Fix grammatical errors & review points --- docs/guides/other_libs/efcore.md | 61 +++++++++++++++++++++ docs/guides/other_libs/images/serilog_output.png | Bin 0 -> 40492 bytes .../other_libs/samples/ConfiguringSerilog.cs | 36 ++++++++++++ .../other_libs/samples/DbContextDepInjection.cs | 9 +++ docs/guides/other_libs/samples/DbContextSample.cs | 19 +++++++ .../samples/InteractionModuleDISample.cs | 20 +++++++ docs/guides/other_libs/samples/LogDebugSample.cs | 1 + docs/guides/other_libs/samples/ModifyLogMethod.cs | 15 +++++ docs/guides/other_libs/serilog.md | 45 +++++++++++++++ docs/guides/toc.yml | 8 ++- 10 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 docs/guides/other_libs/efcore.md create mode 100644 docs/guides/other_libs/images/serilog_output.png create mode 100644 docs/guides/other_libs/samples/ConfiguringSerilog.cs create mode 100644 docs/guides/other_libs/samples/DbContextDepInjection.cs create mode 100644 docs/guides/other_libs/samples/DbContextSample.cs create mode 100644 docs/guides/other_libs/samples/InteractionModuleDISample.cs create mode 100644 docs/guides/other_libs/samples/LogDebugSample.cs create mode 100644 docs/guides/other_libs/samples/ModifyLogMethod.cs create mode 100644 docs/guides/other_libs/serilog.md diff --git a/docs/guides/other_libs/efcore.md b/docs/guides/other_libs/efcore.md new file mode 100644 index 000000000..ffdea42aa --- /dev/null +++ b/docs/guides/other_libs/efcore.md @@ -0,0 +1,61 @@ +--- +uid: Guides.OtherLibs.EFCore +title: EFCore +--- + +# Entity Framework Core + +In this guide we will set up EFCore with a PostgreSQL database. Information on other databases will be at the bottom of this page. + +## Prerequisites + +- A simple bot with dependency injection configured +- A running PostgreSQL instance +- [EFCore CLI tools](https://docs.microsoft.com/en-us/ef/core/cli/dotnet#installing-the-tools) + +## Downloading the required packages + +You can install the following packages through your IDE or go to the nuget link to grab the dotnet cli command. + +|Name|Link| +|--|--| +| `Microsoft.EntityFrameworkCore` | [link](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore) | +| `Npgsql.EntityFrameworkCore.PostgreSQL` | [link](https://www.nuget.org/packages/Npgsql.EntityFrameworkCore.PostgreSQL)| + +## Configuring the DbContext + +To use EFCore, you need a DbContext to access everything in your database. The DbContext will look like this. Here is an example entity to show you how you can add more entities yourself later on. + +[!code-csharp[DBContext Sample](samples/DbContextSample.cs)] + +> [!NOTE] +> To learn more about creating the EFCore model, visit the following [link](https://docs.microsoft.com/en-us/ef/core/get-started/overview/first-app?tabs=netcore-cli#create-the-model) + +## Adding the DbContext to your Dependency Injection container + +To add your newly created DbContext to your Dependency Injection container, simply use the extension method provided by EFCore to add the context to your container. It should look something like this + +[!code-csharp[DBContext Dependency Injection](samples/DbContextDepInjection.cs)] + +> [!NOTE] +> You can find out how to get your connection string [here](https://www.connectionstrings.com/npgsql/standard/) + +## Migrations + +Before you can start using your DbContext, you have to migrate the changes you've made in your code to your actual database. +To learn more about migrations, visit the official Microsoft documentation [here](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli) + +## Using the DbContext + +You can now use the DbContext wherever you can inject it. Here's an example on injecting it into an interaction command module. + +[!code-csharp[DBContext injected into interaction module](samples/InteractionModuleDISample.cs)] + +## Using a different database provider + +Here's a couple of popular database providers for EFCore and links to tutorials on how to set them up. The only thing that usually changes is the provider inside of your `DbContextOptions` + +| Provider | Link | +|--|--| +| MySQL | [link](https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework-core-example.html) | +| SQLite | [link](https://docs.microsoft.com/en-us/ef/core/get-started/overview/first-app?tabs=netcore-cli) | diff --git a/docs/guides/other_libs/images/serilog_output.png b/docs/guides/other_libs/images/serilog_output.png new file mode 100644 index 0000000000000000000000000000000000000000..67de0fa34627a4854bb9107d6367d4074c2aa844 GIT binary patch literal 40492 zcmV(`p3`B8P)whO28aP-fEXYKhyh}N7$63S0b+m{AO?s5Vt^P3H3mq)CIOoS zY+`^IAO?s5Vt^PR28aP-fEXYKhyh}N7$63S0b+m{AO=E`0TQqY%#Z{#)b8|9d+6>X zF+dCu1H=F^KnxHA!~iis3=jjv05L!e5Cg;jF|hs&*b3MzAqOQTCGx8v9Z`&t;29#K zH*+LmgYZqsCZt8K+&5X(J?QQ2^}L!<5Wey}`reD?!boB}MA&{_nWA>D z|4EE&PBte7hyh}N7$63S0b+m{AO?s5Vt^PR23~9i>;>$^T$FCkLVQ#dq9Vf)Mgn%o zh@6Z$5W)Qtor;a61px`zrAJ&?T3V7`ZucM>qE;qgGZv1Nx6WhN?RvyMXKb+IKDgX& zrT>FXv8(Re=h;4#{6i=CJ94*T%k7IOZCqJ=hO!S6`cGizr3NG>yf}RdWqVWGLMNWd z7vu|KfEXYKhyh}N7$63S0b+m{AO=>(fPVsZq4CUX7GH?A6IU_rn#IiI4V>Lyh9r%M z$pzN*>H*xGbHjbN4@H`Nc8+2!5)Ff@xF|%{lhtYmSyVn+-n@p%*?HV^jo{p&YNR{- z7ejWOSWv`EQU2LFc^0le^;`9Uv21kT^lks_8`~t2l*Kk-$nA#P{SI~~%5C2E#w^_9 zuOgo@FjkH?W_^!$&kUecXGa#6guEaGY%W~a>1J;;mX0kSFXNSey@#HsZaDukj2%Y` z5TUP|MI&o;5*>eZA~DQ=+gsUgt@fo3Pr*4>;UiMBqF&r_yRi}h`(?6^kv}-!C0{P1 z=i7dydSWhda0JeY?LPK3I$nIo8V2Be*pE~lS7LvlTOPmpZkb=suz1z9tNFvK>|l@Q zWwVscD4M#4eLu{@`RyVEK1fPO}7>q66`Db!zRKvJ@IjIpR1)IMHD&!=68)08do z`H9;9{Xb2iW#IraGaZV5vhTPRy9oO<9Zga8TiM5-eJr&Y#jYD@`)Ltf-;bgGaxLOC zc_uu+0!4R5(D~pvvNQeji$C?!Z^)L!05L!e5Cg;jF+dCu1H=F^KnxHA#K4QiK)?bv zV{xcG?ZVWM6Wj80kXO-xp{ZG%txu2y5XPcW(0&oqGuP4IHwf2?1?(_HC8QxOjlXiS zqYJp^%=TM=sXn=gTd$XT>X7S7h?X79 zn05VjfxuV-%G>$U9H(&Oo*VA*Asp`Q#cMm|_NfB48$-Jjr8XN0*o(K`)-3VSi{1k@ z$kGT^yd7&PU^g7iMqFMFQk;F*{n&-d<|x1IYiFbN-oF+C_RC-&BR|Ok_9D6-Pho3~ z95bOMV22?*H63vq_$wFLm#?Ai(|%-TcniQredFKp_z&**IBb}kMaOTtkX4q8q^3?Z zJeeYYGqPJk%f6k%dP`cs2U)avW==ka;T7J2Jjh-7}a{JS<<&$Mdd~zF< zRA9@p3tb=VQT{0ro|1;R4cRDqe;Ip*DH%vdT4emjqj_xB^KA{U8u zyHWjTH}+gC@ahL+vB(^qfODw{(II{VY$g4t-@aG_CGscvlNcZdhyh}N7$63S0b+m{ zAO?tmXUjm~0(MwA1}2Bmk*f+qg$Ku>%rIuzXghfnby<<%OEpZJ2-qyT0t4f7m>z0D zx=xtoa4<(2YK{!!`iWi0(ahdsY%}^MUFa)T4Vd0`74Eb32-lQjResH>MO^R9vJ_;^ z>h~91#)@&o<%WB($!q;^S-`%B(a{Mk4(&!fV=xl1=ijWfY@cMKHJpK6*CS@6haq!x z1|1{iN_)5RErijK!i*#FptmW2+a#H+lp*j(g~T*lr<^XU4H z&(Pd~Sj`&TEG{3LZVyZQ`3%;bZhG|fN6_)zQLletu!wZzj$B8} zR1*@SHNW+9t?xjOXO0R~etR8Twy1TcUY=a>4E2bPQ|Nkd5J|e&5_U;AdkgLFHlXN_ z^QdYKS7KAlz^?02Z#c2d-DrJ!Q73dqB7gBdS_gBLV@26kTPEzEsrFB@|3lgSEUgty zPp)Bewz}W3?=5uwtrsb}zOb|wH2!)6MfvJ)t?H(I>N$^WLAD?Uhyh}N7$63S0b+m{ zAO?s5Vt^QU85jsyz}6dwFBeiiFpa6h#gY)hXE25dvC2xoj<3VutQ(6XJ<`${KIIno zVamOTnekzq*js=Yk2uX(4608~@$zSU%jfN_JF|#u zZ@h}rH>cpbJBEvW)kxDVLBhp%qx$vjH2Z8VV7qaqzaMuNhp;Oyv;}P5zoheH*zc-Q z?CVHQk!Ecs9K8S|0XzA^IJ*CE0O>^;h%eiQvJYHnIh*g{!-14bm{T*oe_J|ZWS^-=3 z-y}Ld=s{*#4ia}ZqvpXp>R**-AhXyc#202G;nh=cet!ZR_<%{q64Ci2uSIS`yWbhk6@0KY1 zihWkwRKfQv2R8=UJmP!dkz_zhJ z%kMzTlgrqoS@MK69fkAnhmoomuvsoj|FndfHX3wTu|WHX4`P5AAO?s5Vt^PR28aP- zfEXYKh=G@tfmIW*!_s!+;@mi1EA;&fy44J9Zus!{WQe6Z^p0RriO9&w!#;f8HLzy})EUsC-nCppM9eVeb?F6cQNN>S z&``k69G#T}Wrs#k6vr@@iQ>=iV`sPO&zOA&QFWwH5-=IdLh%>(QQH-vh;ouZIlfi- z%mwWI3-wUSZ#|CgzaB!ew1zkrIMw6%4VCQ4`E?brMPHwteeSM`eMCRBTd{=5juyUD zg$vti9bPlA85bqLnnz``DwZakxry$nD#d@iykOSAPJU+s-S_IGe_TlI`C<_@?J7@F z`7w!z+nk5Ao_@6aJcVsLz4vSTWb~c|dAul-ZD_%+A16>=>6;(LZ;ZC-H(h9dSH3Bz z-_Ig%>9rN5s?_d)|Ad<5(i6#e_M*UbohU+FUq(ue_K zfEXYKhyh}N7$63S0b+m{AO?tmmzRN65wKZQAzr;Ui(7|^y_U%kVA%=S;&)bCKBIHT z@i~mYR-g!A@x=!)Jaz>G`x>$PwR0F9If=S-{{$i~XeMM8B0p9Ai@mf2%28Dy)wai| ze(ip<_jUsI#g=50^xwhaU?XadxO@a`_t>D<8rTPFeAoC6RRKG^z7KnUUO?L?L#VlV z00qri%JMFJ37D20Yi1vhK$$x1y<|$D_7Qf{Ze_vJjjEO~#2p_-`;Ag0zO6pQQL_Ix%h>-< zH@biJynem!#fo1PQ^Us6G(=1Wr-ChT>?=E2PB{hF&_uIYa z@gL~%EOs->Kb=SGaIwO_U43GI#;qB10lT^n?O(kj{{tny0rkHOAumCW7cm1{*nj_% zWpq7w8wF)*zT_T=S28aP-fEXYKhyh}N7$63S0b+m{c$pXoTEJ$GEVP`T z#+|c`UTe>4jTnf4&BCG(pA?Ts&1^j`FwY&61!m?bLf_;#4i?JmzH&i2t@Rzu3^qvX zNo(u(_kBjkFx+SAq#3<-_4`|YXxkU+m7822e9ewo5~u`vVc8@svghMAYzG-%os0zf)cR9%TW3K47N8o5Y>AT z`+u`rxq-$UQHV;9N4RE5Aif55*X?ay^^5-Kx4|AS%3~4PD0puM?F&ta)2#0<_Sh+2J|e(4;IP-XmTqqyN9qVMin?&X+K>~{SmO4qZ9+v3m6$04_N`5-yq-*aqPTR<|C$=3D_*0i)pHV_!1I5 z_nQ$eEjb`B5u#l}B-YuF+T%qlT0%rS16%6@X$gxzt=|$Np=lrQ8Q6i^$B~?js2DX) zcsX7IHcLg(zq?THzNQhd`4S>asOeB2EEt}VgT$OzFMe4406HJ`BUK->emrE6F9Vc4 zIfs2$%8)nj#;$>6rEC^mkGiL0DDgZ*QTpxOd9QV%g*^=W7v%Ahjlz;_@@4SMKd;?0ZL^VJ-x0v4n`|t9~1lfX(fH z=boYcwe_&f-Dv#j4z|{+%K>@qXPdF@+Xd{{?ai3>H}sxtLktiD!~iis3=jjv05L!e z5Cg;jF+dEwybJ^^U~}Q4@W6G<-9Cx>yfmbxd0xq}@(gAcj`;L!WM^k1yZ%kMrr*R) z{ysYy(HgOe#aH8$%Z>T#PULF8XGv%poW?A^_|@x3&*Ps{5XqMmU{T1OnMeD*y+|*~KwMEV zihnbQ&XIC3X^m;b@tKX1FXbgfxV>ZF7)BSL z2|Te~_21P=bbWdlxm$CPu%jM3zUB|IB>hZXHd>yvj;UN6rSj?aizL}>9Ft8GN* zX>@;f35`G8KvBMWvxLX*#{2VVzu$q((p;o;_M_$T9aQY_USi0rf0~;u0UhsUpGc%! zxQVX6oJj5V=We-}rA?cqOWT8be8u`h7&tAol-zJ7T08 zMBZy)8^?4PH$Mf`@JCo)H-(B*DaX2*+t z%C_=#?EU#1@^pPv_WN-&gMRz+4r0jn49)Hv2K(J-QKOk{&0@A=7i2tX2iNoDAH`zEIE z&13fVRUB>J;3a}YX4j(c+)Yf)Enwa?jw^5ML!oXBT&wc=Lm*p^U&X}C9A+kO;Ozb~ z?}tFz)Nd6aQvYxI_J8&bc?kopfX&MZ-+B}-Hy65JMZP5Pmg9|CH{8#736WR+^&Wbj zy5aomHB=20Aj0D#d5Ml?@cr6X&(kTCS9*l34OQ6s!EJQ@d>{KC&!F|a*O8g2id-x< z51YoWVBez!bbU95`pY{It664&#pPqu#4z^$Fc0UqBdB}3%=%V*zwnSbbheMYiSD44v4_MhBvem9ExOO=S##J=zQmCb!1+FZUM!&j_5WN(k7q4t z?J+F99HomR=zPri9Y*D$Jl~nj+Wu(-Y^iN4JzkT)#0+R{Y)GtpeZcD>irV%Xy=N>H zo8Fs4+d?xEG_$x_KK(ZIGv+uaQVwbnC>1c{yb{B1x z?Ej0${+j+P`wKeI^2;bnN=^KkUV-gj&ZFggf%-63KYcIipsk5*$&M>xnK&Yjhyh}N z7$63S0b+m{AO?s5Vt^P3T?YIUuuDr&Qc{AFf^;tdnH>9U9m^a^*uec#Qi_t&0;E|i z<6`EkQvTpb_c#Xo_-yfJ6lerwvtwSA?^#9_dU|`&`_?tgx!o9S@?PHJMd>H?wNW@gtBeU?uiO=Y&YGf9~ zN=pink16(u0b+m{AO?s5Vt^PR28aP-fEXYKhyh~2i~(B#+w4I4o}eNIhyh}N7$63S z0b+m{AO?s5Vt^PR28aP-fEXYKhyh}N7+6aNNWi9bLTQ~)Vt^PR28aP-fEXYKhyh}N z7$63S0b+m{AO?s5Vt^PR211en60ix(kOXrr@7hq=bXSlVAO?s5Vt^PR28aP-fEXYK zhyh}N7$63S0b+m{cs>{)0hC7S26CI#mwXloZVlBB#p?$1=jTH0ohCx+a6e8=%YSq{* zDjzLxUc=<Mm?U^a||D?ZX-d;C$GR)G+`3VrAF0*vE=`amVe(N(F4KeY*ZW ziu!jd5wk-3tVMrTQl{jezxN|m$CN08v1nwCPNL(FP9&QAM*NnxYHlK1kS&M-Vt^PR z28aP-fEXYKhyh}N7$63S0b+m{SRDoe7O)wML+xo7riPr@mY;*XiVh4-&Ejl*f-KOo zXcV+x#PrN{^!E+IwPFD~3{eSbNK50dT1d})qTxN*-7_xKPF_x9qo zopSqB0o#qC-HB40jRfq)TW@QY_~=FNff{7#gv7NFuzCMeuS}r((<8{;o{PlV7S#T2 z0S$*z{I)N*(Tgfz``V`&HUGJY#>1&AvX31{YrWr2z+UV6sr=PR5Cg;j zF+dCu1H=F^KnxHA!~iis47{ie1TJ8Qm1AIX7#+Fl%-X_(<4|T8vuw1TJc_!kNU-8Q zOq&SUEV=>%<8zoEYC*bAnB_)ijx^L98OHS!yO5)qCCu1n^i8_ZSFFOB-gXu4v-Jqq zlw(zX&8bCP@656k9L?(Y7YN3Ram3|@d$7rC{cu^pzK7A#2`monMm%FM60qmrth8*O zWTQ2hfz4P3ia%M#&Ymcx{)D3!u;<-v$}%!6u@FU5*U}v!-Kk zK3T>q|9a2s)$`$AM2p|V=3&$AVYL0|M%VYFs2kd<93Ow`2HJ*;z*r16F5kzVp?vUJ z@%f9h*xn%f+_L_heQ16L(sZ+=1DSzsWS_X+GuVBpLbVT{!G3#K zp27a@E$n=|4ACAo8B52OkC(CYOcSa;pMmqgrqDE2hd9p~-nq;aoV`z?YC=Rd;yB)N74Dy9QG{kL&2>n zblxgcc=9)f=yz(4BU_Lyhyh}N7$63S0b+m{AO?s5Vt^PR28aP-;ALYVU;$fiD85`s z`M@-$4i`%T6`!FRCWJ~W0Xx19gR^cdj`T=NXZVy`+=nUmB4);iabj-)ViW-|2Gu90 zar1B)62cf*Og^0NxNvz-x|cx4c=HWifqwx>7jUzb)aU0UX zZ(NuO*k0}PYJV7#E{tLSe;h|%Wge0{4x#azITEmG4Qa3ZEMkzhH25M0hyh}N7$63S z0b+m{AO?s5Vt^PR28aPO23AeL4olmOi*w_6twP=gJ{+OdzW#N_I;Bb^;`**XbY%<_8fHklg7uGEW{wx%KaUZo^5sJT3E=|BW zzE$p@X9o7Jfn;TW#>fmhZj`F~KUs$NewSvyu%CK^!OMOu6UCq1$IfmwUSjqgMAeZ( zF9F}5B}5!OgQfzucl)&MPe#!nmeF`v(3x;_001BWNklz-Cc}c=g&WZXGK2S|&pn+D^b0 zzq8u%8Kpap&td$v0!8qPFFt_bu`3wZ*NEM(ox|wJNz|qL3Y13W@)_a@S%t_?RhP(+ zmOwcw3yk_>jOy3_#^|%1fPJwg872L9usGO=njd~ z(O>O0SOMF-eR(L;3H+(Uw1kM(_Viwj4YCE`o8;F3-!lDqL6pu*FjA|}0&mHs3V09FsZ*m+53&TA# zR>P3i`VM9W8>IE5%{pxLeMZMH+-K_G-~y^m{Z{2@_t^{BNpO_*V`^a#{YNK!1?*Eb zUV^Z;Z1H}r1#HG=$QNcK{lX3Oyx$`EgoRgN$D=tko~}TWXL*p^@hL@sRod1t0O!Mg zq-y-g_whB%w|+Z^svghM6=DgC%ovY9w_w}D3)tv9hT7NTkUe=0oA&mheYRFwn#P~{ z8B0dthxgHZJRQjwZ^JoR35Tv7Qd`z!2KIUg*jDy?)&jPA14OVu0ydq91Pin!7Kj02 zfEXYKhyh}N7$63S0b+m{AO?s5V!&Spf)cQ~a9Z`|IHuoeN1nmVR?!Gs0Xs4ZQ9ALP zMb_bM_XxT@4~dj#K+j_QV4*B}jIPwQ8?q8^vL|~TFhTTsu zU}J)8e?Fr<^Onn3z^)%ar=ft&m%vy;O^18~g4;1XBL|5&u^s_C356eyqjK~Nw(ev| zICCD`ZwzA3g?xFxpY=x{xs3h4JB)3g&7*p+I@?+6x4>p#``Rb2|82Bfkssp7n14%% z1U>`X&VE@a{@i;BkyvLxYL6FrFCoJH^Y?zF>SIQ;Ryfmbxd0xq}@(gAcj`;L!WM^k1yZ%kMrr*R){ysYy(HgOg#aH8$%Z>T#PULF8 zXGv%poWVAFu-A%GDT zsQO_ZO&2SXv^f`PJ^iTv%dD?}U9=yqPu@j&eV#OnJ3b@YBT&l^A?*6}Fmku%AYn&6 zc6`krGMFaq=Qho{J%hau&Y&=h!O?vNdmh|I-2u<>{??z-il)bl=>F*pay2(Qv_1<= z!1lIJVr?^O{&NwH{i$mIuE-B@%+Wl=v8Ge-B@4WP3)t57<4mPqzO6jOQEJ~`7O|^e zwJ)~;8$UhN?%1T!s;`r6;NZ-Ieryw$lKSWc0$fUV|?LhkVyXgL?2gym{h}g0R zJHMGH0hYt;o~}*iwU&%Fy%nO-$dL$L#H^ zINH3yYmM#5>{|4lyNRi}1O)*U zHr*b^-bV{?em92tt5t{#SM3|U`yd)0%%bb@3|j8(#m1{+z5+H&M)u8XXn%Ykul(yh zul+1G9|e=w(EgJf&hJK1f2k6&8aDWh@1DoUk;xyzxb1bcJ)J^Dl^V?c)t`vM-`z*o zy*fnb`SOT~fe6@o`*d;pT&_f{#y*VOZ(3hcbTFh?L^~g(EXxq**s?gKhi{7`cVb1NwV3WLjiS{@2J~+l%SOg-ok`WQk zkoK+%?e7+ofJ-7aF+dCu1H=F^KnxHA!~iis3=jjv05L!e5Cg=3-wfCb*p3K9MMcT4 z$Z)Uqb4lC_PTULDetemT2;rNkNQ9frFt)0P3)sr+dG{b1qSP7IR>wUr`&ikl*!RnM zA=KJU?V&tJ3=jjv05L!e5Cg;jF+dCu1H=F^KnxHA z#6ajUKms;R*QXh=!~iis3=jjv05L!e5Cg;jF+dCu1H=F^KnxHA!~iis41^>DBw!Pm zAqghkO9jce^CK3b0 z05L!e5Cg;jF+dCu1H=F^KnxHA!~iis3=jjM!vG1`Bw&+(O$-nN!~iis3=jjv05L!e z5Cg;jF+dCu1H=F^KnxHA#6U|kLm5)Ff@xF|%{ zlhvw`SyVn+-n@p%*?HV^jo{p&YNR{-7hrdsSWv`EQU2LFc^0le^;`9!<()cwc{m1P zEFAq44fw}k5*%S+Xun#I-*-nKj78)0y$1Zh2aVF}zrU!#*EjRfkRrFAu~?j6YQX<~ zSb(Z9`MctQO8j~$#YY5VVM)jfLcr$2b)CWNZ5Ef0P2*Rw_t89@e;-BNg>8slfql7s zSi=CE5Brho>4TNcp4C29)QdZAH&!BGN9=nG&IgB(qM5PIGF!0g@ilDD^PfSxJ~Nh% zEuSo-`FOgI-|dbKh5d|0BWrXL9e;EpaRu?eT5Xs3`+Gl9b#+U2{dgI5J!?1XepTW} zYd=j4WsJ?@m4Ce_y?UOWL!KWuo>GVJ!Z}u{s&VI@Y<8_L{}l zO3HYazxB#bn)vd!O^Sa4IM$y!l=9ce|5E=)%=5EZ{c92bM)pwZU!i?{@?*5|IXUG0 zZ<7CwY_%5ODfV9@{??++&r_L-eOJi$TKCcC{AvgM~U`uX^8 zjqGdIKQ%u_DdR1F+N=MK(*6MBFXZzZzdke=pX=@LynePjziRuX9e--Sf0^HV@f%wTz55&~}=cAj>@b+H@U^Rtm#+=Sz!3%KUY z_ItokeR2`EUN803A=i}-z0LFFRI=AKp$x7>mQDJJonNl7UzjfuncpF;&kL z0sDgkG1!n5jZK?VaQ;p$e!Z2B6viM6*mZdFMKx}0mD{wQ0ygh|>Xiv}e|iMD+jEgv z+k)D^Eui6$uYhi43n{_9fC4sih1L0VZ=JJBoqu^D1B) z^=Uo7Q%gz=`AJ6hDe+n+2m4NNle?J9$Gh2%9wHFXVz-}4ZBHNkUn!nQdO-W-hOq8>l zTP1(4W1TB$zgc{(q>ShJw~BvOG3RUTp_KoO{BKtOTExG$-{QSe{|fEvl^=M13{Zd* z?J(O0+CH=LLhXB{f6s`&P_xHsw@0z>3i)2`cIeCViXVP{4KRLIvwtLDdy5NtpRL8` z)%2fH`=s(;U;*2x&t~6g$Dd}uq3_o>1{6MZ`B}YwTw4JrSYjcHrmmswAAAPq80s%qBF2-*Sko~$pP0;G6u;p!KyMGD?MFAdz8^*1&{pO6 z_)|B~He3Y8Vz6=fKK2adLlTu1XR*CO_PJ&KIs4H3bPOe1R6fJoPND1J5v1v6kq0sZ zoBKby{}Q@C?vR$oU@?`bel&sdtr~yw8SJ-*WjqRQxpEA8${{Y^6@e(>$l+3s7~#7jAfws zQyxFjN_(~Oiy^__ob6<>CI2YY^74gZ_AyBVTb;i}{^a8WtNd+u{`-=j|Nc$MKic!3KlZiizu2ebM*{)Qr~kVAY879W?eo|% znE2=Iw`!jqKm2$pzV8Kb{xloEiT+vmSJ>ZbYdL=7|2(reKeJVce@p-H{QlG+zdt;x z{L9nwc+WrQ%;Lk6A2B|*8DCl1mha>I1Uo*I;>Se5wmm*&%{+z$e z;#W70vg)fcJ~Q|Su`QogeDUkTZ>;&WY!@G2JTcLa#Pyw3{aoLX#<%ABj$Qw(+Q;_= zo!>0RSE6p^{BPnPFMUFv-?)Ag;P_M2Z?_Ftz}6ScmkTK$n8wuMV(Ef}&+rQq0~IR) zJH8Hsvu-So^dMhn0A2?dzo*=bm>D0&iM<7g5y_Fop!(!AZXPZ}0vCK^^5J~Ph0A-q zms()F{2AZ!d3)>5EaKW5uj2I0DY)*A;bLF4uefPazrO$a&unKAp3LMRJ2e|0T*}4Z z-9j{mrC{oda`Yz}2-wll*ng!8|MzY-vK0Zl4!65=@#P;1Q0rh=UjduXFkV8{9?c0x zvv@mS`zCXI79IDykzKh#p27KG9(AvHX5hyrA-*sh39p`l^ZOInusItE{Bus6B#?3Y zrw&h|d|PWUWP0h>i{L)G_F*j5{k=>E%ae$c8Bs2xbXI)ScF z`;ogf7m1DSsDC(zT4$W6J$?#w%z+K}?xVIVT)EH}?dAiduJ5j(qO$;rW!q8q(L6dQ zD-j_H47`2|`)YhC%F}NB5m@<*^X@+!KzdOI;>)(7>;o5C&gLuabR?%pcU8G?+hZbN zcYM@~{2jSS+|`A~M~kRCApXG-hNKH)*#95Lkyn|ApV{ASL70b9=>XU~g2`2xA) z-w$JB)dnOrb?fT4;nUWB`6z$D<43*0wo?20*w0{KU^W0?ECLy0E_8o-7&#TWNNRlr zb$^*t{({TnkH>H4d;?;1H*|PA`TmqkP5+*spRM9c%CBQH{^xg}__FqYn8@#8`6&ObC%=bz@_UXazgyLBl;3a9 z8s>L>-^FLE_)_@R<|ixvtnmD{8vYmkFx;Bi_fOZbIY&OH`}AKk{$e)#DfZFkPpy6U z`TdIS{P&&i{AVR#>+9Fq*Ran9Ia$e%1_HKE|8@D*D!zQ|qidgi{_&iDO!(scvud9$ zKQ{4gXFs3*8OFD{e{IXR9lu%IhXon`_WsF1=~p)S-C}&D#D|H0eeA2_huhDJKRf&K z{kG#ni}RBxU%7zQ#gFay+a`YP?H_>*i}SN+pV`*VzEb`A{G=J5o0TiRw=Z8_`pJdHbx#uXfjG9{-udFR$A! zK7H)3J-_ntxdq>L_T}|+0nG6FPj?jgPy3zJe`Pn^F4ji)g*R1Ihh^ za6Wh)Ns@kHaQ@fC7vtk+i~P#lY;8XS|7iJI?em`x|7&~wXxM*^Uv1C-Ht}WaUyp$8 zb$z0>ufBYpeax5>-?MG6VeijwbpNu1o~QS*pTFm?M@N+P#MKP3Ic4*@&S_~rEno!>rQhL?Y}<99#&V;!H?*Oz8?U+MR&CSZr9 z?Z(BqalBTj-f<9(v6_L+e-j>`46$^FI7Vz)R3b8R^01|@57+Na;&8G0mwy(s5&H%w zaCi6|u1vTve5gW7p5j=sH7cJE!0OK~!aaEgt;HKru-%CZu6r14lm#?#tX2KuH%41l zn2*1Gun}8JH{ye12{<@fih~(h`280}XpsaCc?S0X{HY#KzpTf9|3?FUxxWR6@;$SQ zr8ThYaCayFT@7w+3kxX$+o;c}!*_fHM(Hmm21|%AE=K=p9+l0iz?X35Cc3ApWP!Kr z0QP;_h1iH%)VPjdyW5GlFh0xq1hNbSH{Kq7{V_+c%EBo>p*l*j{kvIIHW~04z#7=R zJ}v?!4vxUN*o*CdolU}LFV=qWteUK5wJ5y=On>gsoy|A;N?4d22BO*T?5IAeKJN|=(thp zu}?CJK3YcOVIgQoAa~a7!d${%Mnd*YrVU`sa0t4Hl$-EjW-B6gf>LRyx} zDr1=_{_H+>cB}a|X5T?n9VztOfRYE0-u9dIwx7hGvHk4Y=MR5UA4~;oYyV00e`#(X zv4lv^ubzRGG{Bn2j#f2aCBHL)?t698KYru^%OYypWqaA?H_r@1Z~j&OgzuI7spFUL z_c#7TS=udQD~~UIe&ywv$Ct=ICjJ-sJ+c-xGrIh4z&Wo=nz5ky2Zoa0dA{TM{h@Jw z*Y?}!y-|D#0m^Ux=-RCM-=zPm;D4jOi0_!0eSbKCEL~fb{u?l6#-Ff{dHiRg_;WSB zc)NVge-;9^(vKjYp`qkQod74w=Ub)!I=lE2Uy6Nn$F7$D&Dtl8REUE{eoO#!zjP`6JNYt=KZr9U&#WWU;GEz zKVd)Z)_(kIcYP-N&%6EJ}zoreMek(qCc}o5hj4185 z8J~LuZ13__`--+I{G@U2KtfR`NLlUJJ9%DmHhVcGQ9n(;aBUQr^fyfc2f8h zevzTASg-COX!GXhQLD=@e_4-ekoh%$|U{kwy4*t{tV?$2s5QKJr~?#HlM7J3 z1kBcNm$Cn!8iDB7`{-HVv#uFf>@L(l8bJD{F6?}#5{2$#$jID_rq8<(?@5++^|Q=9 zXnuMFMfnV@st;{H97m>R85-fQKxbg{<5}u1)IVNE&z}w;QIo{w{>`JZN%d*mTkop< zTO|S8>!Ez91<38*Ed5JCs{b2v`-;AsZT%4t!|VI7_wfSSJ{dyI%>yWC&hlEmN0e=x z;N$^Foo0y|ufLG9Jd{ZSusQ(X7i9h}AtLHlPO!SXBnAN5HJrWcx8_rnZ?@G6*go+i z#lL?ujCuKr{WN@udKH1jN5JOo_vVie2(-NLGFVh9(t5hE{r)(*e!78@?LvUvjIH1B z<5l~MI;G=00~|~HneitLaIM?t4}VfSOa*Lf|H<)TZXY3Fx4cs(&)oOS5Q>Ra?ZIje zqy49o$c|)S+56D^%OLVROX%3ety zS;ePIthQ49h61)IUyTnXKl#Zo zuh+bP*5g}#tl#zvQs50Fe+ZkJ_s?#8B@5VQ<9o02gY2IuOS?5X|M=|JjgPhdw>!V_ zviyxt#r_(ujM}FipZk-aw7=)=(Z;v7uV(M9jL0vy;a-w8wW&CcO-~I8QwvSftmHunm;LrI{YNyFV zQZ4-}`On(EqP=GMRqVIhD&sTV^(#NlmQSnrH50J;O&5(Ft=ea$AIbLfzJB!1A7Xr~ z>XG{Mzg7RN+Qs*&^{eAA?J+WcR_zn{Ia1M6_3e}D5$Asc|A_h&KE3i=9?GQnQ{$ia zcctS`QHR+!XaSo!ve0sV8h6e%Dr>{(D+@%xW?@l?Pl`vR1~x7*&mHs3V09FsZ*m+5 z3+1I1xFDU@`VM9W8+eMrJ^u^B^cUrL=U4^q)G`$H zZ^gu^Lj3b?wr7T{W({l>hTTK8`1MA*vQDs8z-F1b`23?n^bc&uub0#rqe@+2NysZL zK$?L#D}H0PEj{9b+dYUn-LYB$oADX)h1p2Ia05N>w@5x=;T72NXbz31E0E;*`$+Ei z)CvXcIaKv{?!1Y=kY&brX5enYwucw6(RmEDug4*K@*Fnp?L+%)t+X_aKlSswu!SGq z2VciF`QmLjCo9$2%9^|7K?&GQUTUCqaD$QvxUKCIi2nknneVIy^m2kTx35{5;(LDu z#E6{D$UWSJ^4piN@8?A{4P<)RftP2T;H*!OssOAe=%5B5n&iscWH$hi{TGb=)EU@5 z@e@Jwev-;J%I_W@*d4FNhq1sRe4^M_ z<6E(hZ|(Tg{#O6qc6|7)d43XQDd$(6fNkeL<#=)a()G_iK77X?R{at6>9>-7Lr}o> z=lsU|qO@NZfBJq}eOB_j#s~hymr}psKWKUUoAaZV?+5<|;|Ht$__I%rPd>g=&p+DZ zWd6Lzf6Dnu8lQ{n6KjFTpZHYlukoQ#`@F}W*7oIn(f(fBH-Fz-9WS@f!oRB_VDtR? zy>9%hVN~?P*nYx4#(Zh@3sFu`*N?h(+3_v&Wo|#wCV#d{|21t;>$m39EPvSgcO^Gq z4f3l${o=n_iGZywQ?{=~{H}(8ZJ{5@_Oqzp&o!{MH<-2kvwN@BA4Gop*pCT10Snk- z3E~hIuvu6Vs@@#O^gHdy(+Qwj2iOYOkx_`!EepXS>+rUF1l^v8M9MRuXEA=TP!>3o zTXESvgk3SJ16gT5TzC3Vs5wzc?Jz2z#i5|K1r-^pfeT(6$IQ_RxqO@Ywf!@C&lrDT z;|_cqobk#-+x_>{#3a?UII3Y!do*ncyDamIttjn z4{_uVh7wCwu$(sRetH2Ll^H2v$h_t96|n0E&}ldT;(tL~LQRLdwsUw!4ia->J@!dL z;fLd>96f`rI~fwroX7SXgV=LHUSrwc`lF9r#{SCty2}x3G+s z)7etHMY(o=v6UX8_rZNMdLGWmZ@^^TzK4C6H+z*M$}`$p4d~^+fSKFZs66d={`Xxk|V>5~t2CzZ% z5MHSs&kRlR7b)!$BC*bX)E<`~@~HYxjVbLNTs!`3+s7YX>W6)#{u>I|cKL<>h0el0 zo*PqU4{_x7=gUxK-?@i3sDi`&;cei-v3zw7HCnejQl_>$ei1{jr9L9O4MPhO7Fehqul_Y!|r<8y2KiZ&|cYuYCE`LhjNz_y9s zRS>Xw`_0A|BEQ&=Z^aTCzT;b~__MQ}s6VLuwx$BMod5k9e>#$r5f!8Auy%dd?hkkd zHvfxt;eqRzyL}S%d1**X^SqK{e2{L{G)-*VayXV?bo|l7y8ombhZ5;HhvCSL>I5@tD(UUDG&C5nkVGRyl zoyE+l8s$NcO8L`9i}LzB zX%=^UhP+NRzahaN;@I`+VdQSjLBfuD?D(2LBrZ)6aIL=)!gjR`fP0kZ1o`)Ihuz!)^w^5eM>lf6WxD0h7H?uk<@Yk zO+QX!`!4l_sBNRsd+Q4n`5|gn_BAR~`<+$$7>h#g>;l^F?L~S?2I7i}QT&@ZbdHou zPod`gM`fj}4{`kJb);|LpHmRY|1xHChnMq_{_YgIKk7kpayTNk?7_}&0=NL@{QYXg zpBP{p4*>k(Q)?^zdoCFBhj^OB5C6TjeGTlFr`k`{$71WS^A{JYdvYaP$8AVPL(YDZzjItagRMukKr;BLgYmiF!)qfWDyJ{ZacI~sXk5~WyY1Dt~{36xw^$;DsedHO~Ekj#8c9mI5X_DXlsh{Wf zpFR0qv%HI0zs2{4`AHLBc6=-4nEJ<#KkNKsSH9S9wY9XbO@0>TnxDVL1&&4hUzQ)T zqn!V~o5M=ae`fWI_StQ%@}tlB$;cpaAc-SYe<;zJ$JX>afAKTAf&Ko3d|7AkAwihWjFDgRoIU#+jt?9Ttv z_0PbJ^owllE#^@HyGZxCPR`PJb1XQkJV*YB>w^`kN0 z{`k+DUxWU8jZZ{;8IQk2*_Qdw%D*<(=XT|b{dU{H1#Fx6T_piq8ebUbM{<6#=G*G} zp4%mu_?7Fox<0qDkLL!D?F1c@8Q6yB7q9qqAYH_t#rTt@G@$;cW$gd@0FpHNuN^mH ze-Hw88ajsESXx^0dbvk>Bq5sr1-$!)!G8By)M#c~vzV+!3Yn3==O z3)n0@8y|n&uxNUT@Q|-d^&(NusMG>eEIX| z0@;pFy}k6G?c&GEzVctBOzc;w#vq@?kl1$`t&iO3dAf|Arz0rd?D0Wb8OoP$qx11S z>|1uCXw-X6%&@Eql-|36wjUPJ{f|jB-EKiroTlv9JZu`ff_;w`(8c5b@(#p$;$QWj z`2fn!e$1wQR`wCLHtc_)r~fwmTh%Ytz!uz!ZO?~$y<<3`0rme}M$cETAVC+qR{i&f zKPd(*@@E*2zYmP#PuRz5%WUGyzx-+(UsBs`?62f^etzWn{YilN{rAgqeqX^X5WD#D zhi^OothxU!&JDb6hW6dzi4D&)CU$ z>7QZ&#J_Z`O@5Mo!}I$u0p@p$f0zlISn(s}ca!mzINoZz8skH=_~G?h`A@XVs()7T z!H<{D&+l1`Uu^Q9REEj;PudqGze@QA@uB8NV}Xkw>$m+3#;^Q%tJiAe53Bx3`z+!| zjbHQrE9G1CkHt5l{>d_0-p;k`uaPa7#rRdK+rs~<|IEj?R`F?Pf2n>x{L(l%tdwj`jc^l_<;w|)e zBcH6VPrT!M`h`1xQv9zkPZYmo?{#IM=_s5}ucIhmomjE1_1oMiptgi|Jb0h~==za( zT^X-d`VraE-j?3+xBBBxdjZ=KfvBh``4t)N_4jFVpuGdv(nkDm1QEhFQIS4t5BpO$ ze~6=)Mb97R*q~cW*Pk*%`8TZWRqXraJn|BK2S9vnc9&cImjDUa&z5IBN7CO^vOP;T z6qcd~%!-N9O)J6L3AvNJJ23=jjv05L!e5Cg;jF+dCu1H=F^KnxHA z#6T!BKms-i*d$;R1H=F^KnxHA!~iis3=jjv05L!e5Cg;jF+dCu1H=F^5Rwd#fK6bA zB$%Om*N56hcO{7dVt^PR28aP-fEXYKhyh}N7$63S0b+m{AO?tm^QV+`%F{lbwkH zVt^PR28aP-fEXYKhyh}N7$63S0b+m{AO=F20b2o^CFG!_q(pudq$7$k5(Wn8hu9|MFayHRX@MZMPcS zk^O_S|I2Q_m%ab15rb4la4~3QKjL%kY-?qAvClsNyU=*%HH$Aq+li|fcgq~Zc=di4Nq&bi^f+lL~}KG6WPEn|^r7*xeYA+nyVRt?6Y^3n345Fv2gTHG~geDNpOUPq5Wz- ze%~E|Fcyu|_Zsm39yCg?|Nf!|U*F6_LyFvf#$s`PsR94{VF9Yb`2mzZ5*L4Q7w^>|1HjQ7!-beFr{(Tg67q%gK1@`53U=0IsKI})Trw>*(dsh2c zQ7`Ve-B^i$9kK5%I3FBBie|<-%WT1}$Jekq&wmE(`pj55wtTXT=Hux;ez!X|6!tR~ zjjYj0bo|kY#1+K$^y+zf z4tajucuF0<3+Gsc!cq1ew^D{EtLdn3ehJ1GcK%oLgU&y})VZF=D(%6en9 z*2s2>eF7|>>pbb_FJbSG^0ipcPsfoFU|IgygMQ;Z{;;!$oqxReB)=)zf}LGgYk$B3 zHe+$9J?+BOkQ3YTbC6fjfuX5coUKogI>8-V(0&oqGuP4IHwf2?1?(_HC8QxOjlXiS z~u=BJFu8ZB+o}Z1};wBs)UBESGw%^eO8q8c~0%57Rt0h{+f^~wagKRtrn?YT&-Z9(nd7SM2LWdc{Q3Es}mtFb>2 z0h>AUQU2$7)O5l`Xn#`J3J)~aT~Hx^!_sT3|C0yMaMh*&Yxy&TgmrIe$e@6 zC1pIz-zx22#h8DV{aI<z|P=0{QM)_b-q(uhlVu@V!=Tp>jPsh`7O`%OB#pbgc#KVEv%P?;7QgVB?piwxIFp zIJULs$k%f@@d(%1I#?Uf@hcOpwf2(y^Mw4PwMi(w4_v?wE62d(FgkM8*`|dD$1(fH zHjjXvjkc3VQI{17R@{ea69Jn=S72a#4%0&|NH+*v=14=$kzrgvu?snxS;CBMM&G0h zeZ?xA>1|ixK3ngV0IbTdIkkxEomrNGjamJ6PE2-|>=&Oq@e%h=fyrPwFo z=mqR~cbl?|3`;CT(bP4x{bLc%@5WGnxe_s+69sEJ2IrGyWfqv2;o0-yUPO!E#O7hs z?P0Y2=tkG~qo^C&svIAG>IT||i@;b6HZI@Co}qm3S@HRcv)JC?Ik{TZpR*6mPsdQQ zMddTR?G(Bm9zmLJ7I`27HuwMkZ|}^%qPo((|0iv@%q%7u78E5YB{DBW1PT-cQL#Yc z5J5zZF%H3?MnR*Z1t=7g93eNIbUJr+XXtd_w(srEWV&z6WWVoyfB(K~pHpY3Q)i+I z6qDzNTBoW`ojp9yXFq$N@7c9?(!ks3`F)qTGzLqq!;U8tsH)NUlh0ruAC+dXe{ly* zZ&o5H$T(vzlz+C2MxXlo>}!+oO>9%_>R^1D+3-v1=eBTDdvpp1Cc99&Gy> zGw6KxDDrdF`Z5dq+VSh8d~8DnDjwZM*V9Kh_%wj_hh5l^rsmHFq>A4^=|-xieai!& zrVFj8|8xeve@>zGo)@Xw8SQB$C|$UV1K-VI&*EN`+?m3GJC$K}Fsh5l-!l{b#0NyV z*!ufrSmqy<{qj)uF>gOfN_n;I$BBKpe?#nNFbHGC2heVEgUxa(QMK%s>?iDp=T7Jh zY>6-4rk2n#sB%U@q#v(I9DFcGlB>aX!XPtU4-IVqo2|6}KWp1)=M z2>vt4(*A4Me~9+6@UNLawBK9C7n}MqKECH{;3?3=5+2{bK8f65 z`j*%8@<$s#Y{nN_TN=IR{6srGvg}{2#-FRvzd7i?jq1(6bJRYg;MXpFNAc0lem3_H zW_6dpw~Zf>^6B9I#V)>y_KUK9ay`wCEX9rDv1{V}N4I!?wjC+j@wJ8j9r@3ueTLaz z)4%dE+l^1H;tRi?_g_}++srQV_jcD?(O z%D!@Z)sLSw@inY}*4WRHe{9CLvK@?$mVCPN{Vt3j&G=+B+Lxt& zo%CO3?N?JyZGDX1E90{yO+OnPv)l4%#TUOX{KA?~qw>h#iQ@~dpOmTP((5PUKa6el zjek?_EA{$@UH#;;m>r{zZ#Mk$e3ky+&_6nTL(@LRYoi!{n$?-USM^?Qi--kmy&?H> zAytFZm^xl20?TJ0#>gGLm4Kb*#n7yP#j#!#8#H__eoqODnDLL|_0AF`%bf#D#*VYo zxP815>0IzlE{5-F0N3_}F15gT`ZM9_^YVHxEaJxL!#IC?3V{draHW4oxVUMOzrOzZ z&#b8wKhG4xmF>d&Z@V${z=NGJ8!+`*6$Ua41ni_F9K2qS|MS2Fmm*+$G2Y|GAAeVZ z##n~uD`4{(#*a|HM-5=wI`XxD^8K^uTIzwTZX?p`TTuUa0p3@FGw@R~k>+tB{qQ;X zzIh!Rx44kbKNqHo0ywvS_UI(K-tR?zWg#+}+R*TL0nLYlLhXU`=vin+3@b*}dlT3b zXg~~eqvG=$*y85)v&o-rKizD5T7b@;kMUA!0!5}55?Qv$k^45olh3wJtY5wBLn<E9WLV5rb zc&TPB001BWNklb>mPf5?f8>zZFJ=QlNDdK@kL+$XyV&%H1X|Es~_Kt z>d(Kk^iOaAAL4&)`_$JztbJMgPrd#u2F_Iw(|kC66Z5dXh+ z9{=s~SL$gOhj@H25wNZN&(pVRUv}ja`*(}}$IkzT{?W#dpulU&k4^iwv!A2-T{rLF zZPVxDmwPkj<0sqtZ9wVooQ-dc%3?SEVyqAqe>9Kp_SXm7hqiy$whx>5!OLvLpHZFk z-*ExNaC{_=udU;goR)F}t6QQ=>>sTBXH!4>_TjAmmdmL>I^tJ9KGno0eR}%O_URkM zM{WOMH-6XKZ>8~nJ@#)_{6|nfy-&2CIbR#z_M_+1LAdMONN;FG!{bHlIw9R3i~Q;1 zm&X6HKx!6Wd0uwyGpv8n_OCYMQ@i%T^S8SH(b~f7z18(%{ucMAVqAE79b4f=TiYaKRiP3vn3q-UO*3jJvpf?A!5s?Rr}@R zzVA)=)Y#FeZ2UWBq@Rq>D*B1kKCSqc^$lwQ+pvFjRK8V+Z+}>ZS$uQipD;c{;+ysT zrJ3F7dt<%C%r2`YV8`U_#+5lgj(F4=rE;cLGqCw@;?lApFWn(uBOh5}2J#Avu+`g- zoAZ-6UZ$>D%aS)?@6ZGuj9$X^i2z2ARg0a6e64&mN}mrvn=dXxn7n|FvP~%2=ELQ{ zJcf2k0-AiSRsQmCjE>AxjK96V2{jd)@cyZE9KBnCqj?4R?PsNE7X?OX2KN8{sTt4y z*o^=CpDp-dX)BHuOAeHm5P8tVf7gIJwK3~Tz&5IL_UQdEfzj+QHjInWe_B9Yn+k0D zh1=+vs+R=b%0t-uaW_)p8_^Irfo*~hsWE((^Xn+k&7hXcqR&71gR9I8b`y@(SB z>@Jl5aS;vs)%YA%ew`2ac_lvR&WZ6s$Jl?efaxgx z2=-85E9gIz`s;ki>u6p-=>{@1e#~m($Lhp?g)fb7WZOGAit)ijz?QF9>aWWq|L&|5 z-*w;1*YTsdeOAZ+JP)Jt+3_Q`?=|f|3Q+c`8ee%iwf(!+Mo!;rYLu4IcjomoijU#`*QRM|zX;;L zHeJ*B@%v>s>VFLPP_gF6xc!FLU-3_bjBD$uea~3F7@wMY)bUvI-lM2L;R#M4vW{QI z?KialSH@p9WmoL4`JEl#cI|`L)$0C7YYVgY%Jp*proVp@?@x{6qZk*yJtc~bJRR?$ zBx$zhwhCT6nJN+RjV27r!+E*^OVjo@l@_Dl(OH4;9pY*Zo z7&@L^Luo~Dg4O0MaRM5@PT^BdJA_Z0_R9tAe+2m)d7$$7HWHn8*JR|NLz1AGvG_pR%9C@~w`3A?HCyb)2TP z#i|I{EYX9*H)e6?SQ!!x;Ik93wFNSJ&!6~gKQjmakrGAlN-H~r(RC_g1{;i%08Q z)fn1cgvak~LZwE){@`dTwrnnd@JS;k8dN7q0(LVVco~Y0*5KQrOjJI{O&mo5E;s`_ zw)?#FbdWzGeAK3_@toB13cR09!N;E@@^e2ehcAI4uc4)B+}uul37DEMmT~aM;I-oQ zOXz*bXI(R}lwD|kGKk#G-DtX62aj+HdHJ1a{j>*Z!L;o1XZd^3_Usl)iy2sbKlXil z2Kkz0Xk>pyIs;p*NA@l>KV3%epAI2IQ%9+O3#e;VeVY2lJ8Jz_Nx;@_%Ez)x;O^NX z{!2m3|L^AZmFsSHR68KGJ?Z}f6xZC3&ZiHt?+?RhxP1sEZ3Q9A_sD500bUauq0Frm;dI3?+!|bRGU^IF2-^v4Y?HX>O`CId8mY@8+R=^HxKZ+n= zzl01=PqCkdFC`z-8Q8r1q5Sb1dMz(J4QW{(^Cd*g>?2;=a2)%;I}2AL19R;~+Ydu1 zN>}|Qmr*Id&Ie)|a(vL8v*b5u2dDhW<$f`bP4UkPY%Z70>Ztlx9p7kwFY#v{ztsNU+&)g* zr(%Ci9gWJTZLd=KOzvNT>G1mj?RZw(zO{8VdvA5UR6g_kO$F?rXsFiDpnnMVV`6;e z<7b2Tsx7mz{jA%UdjF*QUq8Op=3(|;;ZxK1^53fcllp)}+kTw*&n!><_e%XWWl-}s z=Tj^vzrWxQpfv1B<+r}SQ~5WppIk=8KDzYf^L9sNd}g>rg*o4neJ$FrnSjk7x@hcZ zRX%Zi@$)T|76tW_Cufi!yuYyITb|G)E|F?2U`N`1)%;bywRN$zPw*dZw)Y?M{k4IA zb$kk)d>;1{3Ez`0;@&I73#m1~!Yq?%_uKbSqa`Cs-?BvwSx`{m6rX!EN~I z?eI+$SxhF1DoT)JAkON`rT<)UA^<@cf>(E~R={R_hP=mx+{?Gn`(C@~6BbvE?N8>g z^L#ZjgMWW>`=?eYV9%kxH~8dH{tJ43a&QLjR@8oV8Jm2k(D-U9T$7iuxw9YpXB)+( zX`JNGpF(>+Tms(!G3&}We3NzRY-Q~%)(B@{b6bi6pskn2E=Xv$o&_M{nQ!QVeRLaB4Ec=qVCBIwzb3}vF{2F{`+nuYT~ubm68ADbIJfv z!v;U+lwT+O$$4pyYJ5{WM(qIKNqiB@DGTtrdP@T=bAA}xirO#NAinABsI9Zvdn5m> zXaH|GLyh0yTh)J!1#E6#i~d7v3#I-#A1eMete=zkVRD19g7$CLKD6bxdav9d>6Spy zUZd3CfE~N`WgcHw$N#*XM&*0){YP{HwisW&F&{tK)sNf7>G($LYx%uhd=k^=@%D)!fK zWmG;b-%|O^?aS+8b^oKStJ!<2>!tFU=f5ffw$b?6pbs{-pH2HR_y?$Vd~0SC{rBea zLms~w3%pMJr_ammvr>PJZJhLvJUt~oY1k9L7bnnJ_%}EM+iZe@Tvo+Cy7cAqc1LA= zW+0H-@@eq^T};<#2KGt>Y_6aDR;QnY^#4}z!`TudS^?Y6R@(DM@gwZKm3`J+z?Sd- zqth?6b)xs-eOXijHWyCoU-M)7>V6dI1W>K9Z3XOvL?r5#g9bUnG`6EUPc=%(5kF>5R!iyIFCqboFCh|* z{lYhKRN9XyU^(}{Vn2=519akbLRE4yMeU+3$c^U|r(<-~3S#>6PWl(I3}*c+AOCXyIT`;(6d(Ec z!@mF4*GvCdw68(@up6K1(=q#O=07|CEB&hz`x)Fnn3c!qd(-&gM8Gy3Kdw%EQ~cwQ zX`}iXeJA@@yM#!JZvc&FN>{Xmh*kVC?H@F8nwL$nzow2-{4nR+N&B?A|1q+O{yVGd zZQ~oCnQ63yh%y7)y8q{8S@HNe#C~?;4@qD)8{g_}VfISJD$F+f1L{05spvgIz}#FTaQ0hL%`-`G#g*Y@x^?JRQdikGpOgp zpuj&DqHkEWKiNKJM>+qf;@cmVVHMwa-l84({k6dZ2DxkspBlzwKAns|W3#f5n5^oM za=LW1w@JhTHlKOwIdl_q<7d%al!Kg{;43Rdn!(KCke2I$%jJTr`85QlUqcgr@5)j( zx)T9O+ktZd0Sh;MaEAn_OtcQo;=!f;s46N%NdsR4dmKlDYizUF5*+m};_lgYR1~>T z=xM;Qky*@~Yfv_NRMMX|NmhX+qS^Wwix%js)oV2c4Y4cFgm!5@z&BUb#Jg0~(?ONj8i+(&BgpF!v23-A;$#P(dkp2y?j zT27*0o#vm{f!3#s==tsf+?t0STK}z$fE_E^k8k2wSfg&@*lYPDEs$0 z92lz-cj4yzCl=(Yn>c>{DsngS&l`}ymz=P90?Nyu`_2@4KI%nQRvhBD?m^SvRe@1k zPOJBf^Y@bxe|7^vX%j~)J}vWQG2$kkX6=VxYi(Zx`xUA7lk;XNUNrp>z>Z$GXzSFC zS%{D4_SJ6!bqLLWTL}5fW!#1wq;7Pf^u1;58LbwtPfC-Pj1m3gK!Awno8^7-HgJlppmdYvao2td638uZ=64IA%1qq2aHK*fk*CUrFb6@k`@>wf!2G z-){V6Xn#%rYR9)&K8x`mue;U#kCkoYb5_@j`CG*|TLIhP{!e3HxeVs<)q4D|`o~N_ z*4#fCjBn-q?T+U0L+0B&f4+&MUH@X1zac*>xPO$>HIGl$_jh*o4M{)3@hMLuask_5 z{Gs7%wFGR&#~0rR^^+7`|8LWOgx%l%GgRNOYJakQ&5o-Q-z>(Da=vB)wjrM(@lDhI zEc6Sup+#JR_TZln8SdXFmxGSRVs;b)b`H8m1w4B6DC8xK^@>6?UxJ|Lmce=9A{sQa ztyyvn2K}=LT5!OBpGZ1R`$Fgtd>?Zy9oQi?V{wK z_%OJs2Gh;J=4os>z77BHH=D36mJ3j!0yfKa;rD-Td2RwWFAqyC#^&)+bUt|q-`Drh zJW`L;I5mhR?LLZ~k7v>SbO!D7o!B&TFI>Q8S#aIHf&EXH@XEj54LQ$JicvCo1N*-d z;QRV6n%}NNiiQn7W3~6`8RYXdm1eLMc$4Tt(b#o#KH=wYq2aYHNYJ+d%~B_N&g?n>JNxR>(|=}m<=a?~ zn%|7$!1qfy_;dyx@4kxse2EX~FJ#N2&$-{_SMReaRBh)^z~upu@c>!0Uw$37f4(U0 z(%k*{6so2pSOc5$cPpGfCj*qI?Pt?|tn4fOMasl}b!r>rvp6#P&!gjsfZk`z=zTVZ zvMoU$ZScov9Ce@u_8VrjUT-IM;ZUE+K0BTX73H-gNKhVq%|Prb}t{r z_$OaK#+4$GYC-V1J?b}KH#4@nR+P`?M&G<|F z4Ug|X2IISChLPR%s}VoM`2N1}_=4we_p%bO?aD8wZPtGHc`N^^*Bg&NoaE1J`foW8 ztD{x?5Xbix@yRM(`J7q%cjAA?_A|MEkjr3nbQC|F2-q*Ue`9Go(frdg+TV2B@~*c7 zODV$Ud)Kk|$wPGW`?qV`k)pYOv+}>{KlAaqRr|EFKQF5t-&XwxzuxZtM{f`PXS?gI z@)w0Iiy7Er{T%cU%p|_r_0Ot*j0I#df1B~G-X2Du&EkiczbF7& z{nGJe72npg-KlKUCZ7ibq3!#Z*MCs^r*`x_+7adPf;ekE3E$5*#f{X+2QSD64jz`R zSKoy8e=pzocD>s5*HSKVeDT;=Kl!!TAewrHw!dHA_%j;Ytj4wW0(NXX5)%`pS3;b) ze%5MaOld^l8S}qU#LK=(ObA}NV*!#m3&)Pn#!H=zgy&9QN8f))Jvazv^GcWsbaH(xY zOLLGdjcxh7?ZVhr)P5!XjqKp}GiaaNgG`If6rOkaD8Kc=Nu+)d`TFwZ=1Ylhy1(~D zY7@HdL(0@?-SN%=wlP!Kp3^108lHV-C`$`&3+Mr1rD`w!AFuwgIwda?y zF3R{qvpnR>SdSM`=3m43^F`QIna~;t)du_PP-{ z8H+_c_e)YXHdT~FBw$yZ2;kA9N8(EmhR~AuD-y8F`VkNWrT#;$DeK0!6hL2&07`x$ zKM@1O05L!e5Cg;jF+dCu1H=F^KnxHA!~ij{whTBEusy~zuUVQ0`(7V`KQN1#$y>O1 zuo9UXftw4gxjP1NdrpAxpdY20b9RnpECDS;s<$q24RWCXn*YnCTABg9~i@> zV>^%=>s)}{{`x~jyp+?w=#^&SI?3Ov4ve|bb345Jv!`oCk(8yhVptF$2v@N?Ln?Fa z=~)Q=!zgA9j8)gkEyia52s)oE!1v`{crVu? zX$AJ>_F*l9@O?Fa>=@^Mv9jx0oMWYZxGxA;serAuPxqI1(R{TI$t$$aTGVGHX^Q^& zasb&nrdE=M{M+o&DfsSH(?bB7#ZC+m1H=F^KnxHA!~iis3=jjv05L!e5Cg;jF|cY3 zL@Z!4mWsyn0Za}1P+MGxqUtUTPtD?DbGleK#*$F7{|csOZepN+2!Ry~*fB^<&p}QO zf4Q;!=m;im_M>}>GS`o}c$}2rd z637{|&R-Vo%#MtuqiR22n&TX9%?l9x!#Lj8ha*i=`BVX0!0_%2vCKvS_Trs4HA{T- zq3=)w3Up%QS_s&@{@K?j(DU&LxVO2H(b$g0zdc0Du?>#x%Wd;Z6|lqY(}srsTEx!d z*(`peYH=I$GTaIqP2nsltvZ#cJzn+FOk1xK^|okGS~8BPQQ z2t%zQ>xWAM_B`(1oxtMoZlo~=BLREiwK~i4i8fk;8Q6^Fq3jRKXzEQ=@=rf`8GGKT zRhE%q86K2Q-N3$oEW-EoJv3jdLvnDYHETTu-_Of<cC~6BK7)OHRGPv5#T_)gS&5_| zn~ddR>+hG*bfFdXpU%Md&ndLt^CC642Dx~i+u!88=ywbIN$1@t9=j&y-!1xQJ5uEI zxqqIS_(v|IUHUnds9N^pz;|=lBkYIg&I6i(O;1;qc;Pfg((lwhjBG)+AO?s5Vt^PR z28aP-fEXYKhyh}N7$6418HiZG)*F*A7g9Aijj7{hqJY6?sK&@brImo4=EcygfW@(1 zap{b(bj$iNB`jjbKZ@5oOOPy!Yb+T%&Q9a@@k*q}FtFre_^t+UZBK59fWmnCGvVp; z@_H{U;>PL2IDdNzfd}_+rGH1bxM`BVzMN*Ctp#iW7X}7!e{mSQQrDY+U5u)~JVN~* zRRGr3k+C@B`)AR$)B{)DMx@ubp#Jd!ysrdj;HP9F&ErD);dAhP^Ex(eaUq?5E=&~# zUT**F(Mfc@-;4apLS!_xq2ciYnh#5}(PIvrN6$htVpuV%-kZRlKm%f!8x^15z!o=O zV#OwZwgIIdEusBlVUWjI6im#aYphBUnC1FJCScpyCl=Ww6X^bU0PY$$GIs7q^H+0d z^rZ&NBMI1DAN8SlyBit1y0P=yMR*U%|6s_));}yGU&_ zyO9##h=#xkY!iG)jj6+qC$FPGH-lO(i$4G4lOyQ;q#LRH0Y_{FwtYQ|x>f@|BUl5Q zabew3;4eVgXG>`8j#uol;q3|d{54Yjf-|sp4Q46l^TuY-b*n->|A%FSo)2iw%l1@2*w;R2;mx?FHeFYur^ zTU{bUTmt2!Brxi)G0I>68>7#50``^mER+x2$KudVG@J;83E0BDp^!DO4>g3Z@x3-{ zV5)TJonQwd=uLg|8RSl3)ovw^Tjd_{usQL zr~lIudLQyx*9VgOSQhcIw*B3!^e z*AOBI8|Ay!0yg6_)i=c|z!Tpq;jpHc)^xt!Jl_8jVa zgG*P)OIYM52mQGfwO?JvCf_MEzM2ZxJ)ex|4(kB7iwr$Fc(J}H)ifl)=BL;{8Vt^PR28aP- zfEXYKhyh}N7$63I-3&w}U~}QL{xv_QukJ^Y!OT_}E?WURArXl>@tY-h@uo0_p5P{t z(hTTX_>X!dfitTE*Mwp0N>-ORU=;%h-0z1+vx%cv2BY*@DoPsLQJtp(P;$hNnUmF0 z`ZoE?b+bD<5wQ947K76dF*fF3M*?>ECXRe##e)x|g#+31lQNlbs*DE(Me3`}Br*oW$(LTs$uhoPw% zoNJIb*|W~y&H;?2qiTO2`ufh{*1Q10KaAsjeK^u2Edjz(S}`mLxYC{pF3wk)Wi08R|3&v;A`S=1n1q`u07qI8? zIJ}2~*E`KWuLG@57t!(Rh+J2m=>}%u7CXQnH{Kq4{sL2DX+f zdQTlSF+dCu1H=F^KnxHA!~iis3=jjv05L!e5ChRO5QTu9gRW6Q6kWOSD!+uWUQvi< z%!Qs?2Iqx~Xwb~IX2~@e^v@!2r33jI0b6u#W+i&xyp8Gk1GMq>JI;(?VrC9Alecj3U}fkgkT&^S0Vvl0c6j|~ zPuEHUr$)f$>BQBXL_pv|_hA(CB}`ZqPR|MuUeFREqU}U&&zOV11 z`RzKSXxQL0zI&gZK|Wt|x%O4;dp3pYdKG$S`DeiM!4kUXy@=QI72I$y5&>IppKflS zYjsG`*oSfZO^l-R+XeW(7=!oCO6B2=xW@JGml3IeE#_}yKbBI2&G)Wj?~{j+%C|kF zd}12hKere?Z$qf;Zqs^SIj}BlKn~9CwFXa^|uP8x|#WF5t zwyxkCM+$xn_4C={Z79(Qux8i1Oy4ucH=`8b?UmNn)|Q>+)uXqs4}EXkz?>jps8w3N zMEe_hA04A)Ke8V&KnxHA!~iis3=jjv05L!e5Cg;jF+dCu1H?cy4A=|UvGGVuOq5;; zaUtvHMw2mJ8$GyunTUAVH;D;|Gnrv*Wos^AE3@Z?A+#i_Gpwzyds)u0%EQ?E!&@lI z2(K4ko1M>km+MagcJxfXEL>1I$=AdHF+dCu1H=F^KnxHA!~iis3=jjv05L!eyc`VJ z3fSbxm&1|dCu2WlUiRbQQX3K?5ckQZ#x^CpkX?uYVt^PR28aP-fEXYKhyh}N7$63S z0b+m{AO@Zn10-P6I<2%$Eiph05Cg;jF+dCu1H=F^KnxHA!~iis3=jjv05L!e5CiLy z0TQqY%ykLo^Lm0q`OwosVt^PR28aP-fEXYKhyh}N7$63S0b+m{AO?s5VqpC;Kms-i z*d$;R1H=F^KnxHA!~iis3=jjv05L!e5Cg;jF+dCu1H=F^ur3)O0h_>FmtfLUul4)X zi+n@AAqI#6Vt^PR28aP-fEXYKhyh}N7$63S0b+m{cwP*UfK3863E0E{F+dCu1H=F^ zKnxHA!~iis3=jjv05L!e5Cg;jF+dEgO9n{5CNS3}n9u784&_5n3yA?@fEXYKhyh}N z7$63S0b+m{AO?s5Vt^PR28e<6%K!=3Bw&+(O$-nN!~iis3=jjv05L!e5Cg;jF+dCu z1H=F^KnxHA#K5{_z*fL!>4hjSFPB~=xkzMeT~_4R_>_djW@4l4oAS-bNm#jW3U>6O zudgroYC}of%F}pRZO`)R(W}(G4{e?VVw(arF+dCu1H=F^KnxHA!~iis3=jjv05L!e z5Cg;jF|dvpuotj1+^E=6fV9L!Bqqcmh6L<&12AK;i06Ju%EqROl86NCiW31mdh|$q z3BnLs5`RSkc3D3Hf}qrYs5NEX`1WOeC_v?2zkjzO-;i&J0b+m{AO?s5Vt^PR28aP- zfEXYKhyh~YWn{pafbB7!dCk&1*!TJf{DE1_Oy0u9gO$kC2;5v?&D}AG+j9bh2mL73 zoU=0)V+m*(QpH7CWIek>1&t*Zqy4oTn4Dd}d|(Whj_p8htaAZ&`|A%C@lsCzqBndN zE{n;-zL9y{?Ahp8z-P>bp4;K&pFLeGili*16~lr6LAZ+D8B&>RPtQW|A4V}_V5|zK zXTz@-W(HBAvm=YiL{St1HW#kF2D7(WYB4tZN6`6X0lqKq!h5+ENh`1~_c3c3gzu{X zWXCx7iya%QeV&!};l3bXB?2~Mx!C&qWxVpQcg5GirvbDt^ddKB?dq95`T)Lr)g-d7 zqbGo?%_60z#&@y>*@74#28aP-fEXYKhyh}N7$63S0b+m{AO<)C5ewLirK0hC08_(0 z)D{<_sJaWoQ?t0(oGuBpED0t1uV8xSCIcEMfNiZgc~;)c)VSm4`nb`f`8tqA5J<&~Zk4o157B4#E}pkf8H zlNn1#)qcJ-$2r`Z7a;hDalEe&N1CMasRFiu;oTWxnT-VO#XE0mmiXvH-=PK+JO=@r zu^41upFq#YC*a=ZMn+>h8vphXEyp%Ewl4?lmo8wpoOB^|V=mGvYf=9G47wk-AaRYv zdJ?e1+a`5nWD{b57$63S0b+m{AO?s5Vt^PR28aP-fEXYKe%TB}E?~!0VQ_L3U2b*8 zspqI4$_!)X!oIU7;Vno2E9=L!iGaEy zjBP>xWB~nTs)KU(jX=2Aj5tj?R_QmKTg1%+1(t#=ORB)&Bp2o-k$I&Jg0V832nY~{ zT0_p zLT4Esluq5izJDyj_w_wAU#mlMP`qWWr{McpouMqxRPOz-6G`%KQi`y7d=&fsM?m*C zci|nbQLaxrcMJPQOTkz&HZ3n<&u}sLto-7|S!`>Od~TV4;a;>oyNB|vDxY!t&Y}CO z6UfocB9CSUwzpTEvCrDipy%ro$Z=3V(Qn*-)5i7_&*xO4YT1ti-_2oI`hQ zg8HqLS^B*iQ^*!%3u1s6AO?s5Vt^PR28aP-fEXYKhyh}N7$62-ECUe>*m}qDi#)4Uj(6|gwgD=wW8mTp-;ri4Yz_($=2X9<#n;xrdFcbuKZ z?c27&-V2Mkar!XM-=0F?!985*-w`5i^4}Eq z-onCY7Yc%P(U;Hev$cRN;KINF?k^5wSL%8bu!~Xkmq)1IqYA*p`_a?9>(0~}`M#bkhu*J=nSh2~UZ9wTqOK87X800Y) z1ru}V8mm$Sc)32SAz-uQTx`5QiG%O&5k+{r`ibSgH)C!;7LUBU)9Cs5I0~!X$n1Cp z-oMT%ONg)))K9J_9bas)CHs^8i2-7O7$63S0b+m{AO?s5Vt^PR28aP-fEZXg1FI%r z$K>qBl{r6-cw$2YWbPEJ8QA=MTv`^4mhKR*P0T=EVG*`^`*CxA635FlGhUN7Veilc z9*kbX^@#vRk5wbnKxj5fp9_f17Z)K+UO-3LCX{UR;c{ReLpvn_R?ItlH?GY4(N`+v z*>Fz4?H+en{rGRqUUmZZ@a{SszrTo~ovElfHD|j9_RL^aSYB(f1~%iuv4wzbRNw5; z`#5l?GNgQFONcNoM*nF6b#1Ec(l6Xb&s4p5J*zx~y&rcYCB6|2ffLv!_>dY?haFE| zM}ckzwOkf`{>djt(ECX@Quzap*a~d>dKPu927E@b2KK=p1@wF`;NY_*_&$FFo3_MD z<+rJyTxRW&FA*Z!kFi2j{Ba45-Ew*{a81lB0ye+SY5lZ$(0i3PvIW_K7$63S0b+m{ zAO?s5Vt^PR28aP-fEXYKh=KLbz^Vw?EYX9*H)e6?SXsz288QHN0=E1+t0SM$y8X-? z{6|U@fi$h`5JvA^$Kc+b*nQ*@?v9;>H#c0MG)kAx5Kk}gpg3DyB12pP z=b0j;Z*4=;Rcm&mF4`vU4()gYo@1KVl+J(MxPNgca!qE&Mj~Ldm_(#y zrXfKyqnZoMbEkp=b8IR4C;d3;i3a^AZHsdqoJuc*4zJ=cR+C`tRxN2;F zGKZb#tC1O89>ndRG8VAE96+|lkGu||K>NiU>U)Dri}2+|_$xm-=+CXF{pvC{`A(tn z)l|49FJW_MKlaZyic8ao`F~@bKVw<&e7JcTm@ZwEj3_Zb3BBdGF zv+y7FNCIb82d)Xj*p;lV(ab6a5V+qDk7g4`u?$A(vs9Ecwxc>vbxz3{za-}^}T;5`E`XR=~{Od@-4&TI)Z>)ImVY4U#v%-DY{p>O}rAzkb zGurd-1i}UE=0O}V6tMXcB9G9}B|U)Peu~R0L`Gps(Ege5eCS8r-3zE`Vo1O67Pj3Q z!k){;(s`c$&-VEzow$aB9~?*RCkxoosV+Ywv&oOq%)nMQaoo|5{Xe~p&AGBYZ0aYM zKTZC94D!cj6#I!wtbA_0ga|LYllp1vO7GS7PPQOh5Cg;jF+dCu1H=F^KnxHA!~iis z3=jjv05P!s8HiZGW-I}oLpL!ueiqF|ImpQgzOqt+GnnI$mg|Dc<$|mEH3X(#Llb}R z%0iMxU}kAMa4sNV;ieC6?e{DbtwXbTaA`lPiV9KEz}LVY$I;*#+bp&ONBxVqd$t`F zMJ^P28gOi67BlA>l#L!afMWX7M(M|*Vqg-}!#-3O6=GxMJ`7FG;9Ns$P(V#YR-qei zxBA-mmh&~R8B0gi{yy~eox`np0fK)R$NTzlq)A!=gr&4%SP&oz*en*+C#OZBT<{+j zH?w3+63~SgHUm2b+1Dq~^T`RgYYUOy(29n~i)bB`Hpyi1)u{h=0j*c+kh#T;oZbO6 z|8-UoVCBZoN)Mvrr*}}*TqMr0PRmOQ+E?1dvHRoWaMu(feS0&u|9KI+PUMK^`Sk_k zGw6JL0iFVe*q#g6^LQNIL&58L{!bj_pVxubr;F(M?gHGJhaGbHL`I^Vfi0%N*9?EW zjP`Q{j_N1c&!YS+Y!k;rX#U$m$QsyUz7FcAtt-7>|3R62L_Q)0hyh}N7$63S0b+m{ zAO?s5Vt^PR28aP-KxH5b0Xqj>qv11@g|S{yh-S=%o?8azg^Os=%(iC9H5l~IB5G=iBj*sAE+s2SJwi8^9=)ZIuQ*#fo5b)#r>Amm-XSB*rwo0ER zZ$ihJ5lqa?VP^6cE*`8j+yqiiYb8sFi1oi6UjNzCwUWT85wLmsaWy9q5V+9&yanuO z2*MD&1~cecYB4sCkD~L*L-@YFhvt!bq{gW;-jjA8#m>jG=zcnb_W4e18o3uPV6!Z^ zZr#BCr%QO{U+;#TXDP)fnY@Ah-wE)2eHYDd*C9p22A}cW`}7R*`6i6DuVUY`DOA_1 z@H)#s1D+3-(5+eCL-wb9T$LHvF)>I#e;d7zUqx214tDjkD?iJrMAh;*4m_R5-en(3 z?@oma*v!6uay{v&vO~5YTMz@p05L!e5Cg;jF+dCu1H=F^KnxHA!~ikyaxmabz^*7q zd3ia?OL9X5WODM0bux?1#76Fy@(Pq!lpx1Igtqfh#R)E8`!UqdXN$L?L?ck!UHdYe zXMAS#Uj%r2rM0!SWoCKx=qH=a3D_ zhQt6dKnxHA!~iis3=jjv05L!e5Cg;jF+dCu1H=F^@M~s(1Z-MDgdRi?1H=F^KnxHA z!~iis3=jjv05L!e5Cg;jF+dCu1H=F^ur3)O0h_>Fmtg*ypDIz^>8UC)KnxHA!~iis z3=jjv05L!e5Cg;jF+dCu1H=F^ATeMnU<-m^DQwabBGibe5fKB#05L!e5Cg;jF+dCu z1H=F^KnxHA!~iis3=jjv05PzZ4E%q}6_XjmNkS_C0000 new Program().MainAsync().GetAwaiter().GetResult(); + + public async Task MainAsync() + { + Log.Logger = new LoggerConfiguration() + .MinimumLevel.Verbose() + .Enrich.FromLogContext() + .WriteTo.Console() + .CreateLogger(); + + _client = new DiscordSocketClient(); + + _client.Log += LogAsync; + + // You can assign your bot token to a string, and pass that in to connect. + // This is, however, insecure, particularly if you plan to have your code hosted in a public repository. + var token = "token"; + + // Some alternative options would be to keep your token in an Environment Variable or a standalone file. + // var token = Environment.GetEnvironmentVariable("NameOfYourEnvironmentVariable"); + // var token = File.ReadAllText("token.txt"); + // var token = JsonConvert.DeserializeObject(File.ReadAllText("config.json")).Token; + + await _client.LoginAsync(TokenType.Bot, token); + await _client.StartAsync(); + + // Block this task until the program is closed. + await Task.Delay(Timeout.Infinite); + } +} diff --git a/docs/guides/other_libs/samples/DbContextDepInjection.cs b/docs/guides/other_libs/samples/DbContextDepInjection.cs new file mode 100644 index 000000000..5d989995b --- /dev/null +++ b/docs/guides/other_libs/samples/DbContextDepInjection.cs @@ -0,0 +1,9 @@ +private static ServiceProvider ConfigureServices() +{ + return new ServiceCollection() + .AddDbContext( + options => options.UseNpgsql("Your connection string") + ) + [...] + .BuildServiceProvider(); +} diff --git a/docs/guides/other_libs/samples/DbContextSample.cs b/docs/guides/other_libs/samples/DbContextSample.cs new file mode 100644 index 000000000..96104ae53 --- /dev/null +++ b/docs/guides/other_libs/samples/DbContextSample.cs @@ -0,0 +1,19 @@ +// ApplicationDbContext.cs +using Microsoft.EntityFrameworkCore; + +public class ApplicationDbContext : DbContext +{ + public ApplicationDbContext(DbContextOptions options) : base(options) + { + + } + + public DbSet Users { get; set; } = null!; +} + +// UserEntity.cs +public class UserEntity +{ + public ulong Id { get; set; } + public string Name { get; set; } +} diff --git a/docs/guides/other_libs/samples/InteractionModuleDISample.cs b/docs/guides/other_libs/samples/InteractionModuleDISample.cs new file mode 100644 index 000000000..777d6aef0 --- /dev/null +++ b/docs/guides/other_libs/samples/InteractionModuleDISample.cs @@ -0,0 +1,20 @@ +using Discord; + +public class SampleModule : InteractionModuleBase +{ + private readonly ApplicationDbContext _db; + + public SampleModule(ApplicationDbContext db) + { + _db = db; + } + + [SlashCommand("sample", "sample")] + public async Task Sample() + { + // Do stuff with your injected DbContext + var user = _db.Users.FirstOrDefault(x => x.Id == Context.User.Id); + + ... + } +} diff --git a/docs/guides/other_libs/samples/LogDebugSample.cs b/docs/guides/other_libs/samples/LogDebugSample.cs new file mode 100644 index 000000000..e796e207a --- /dev/null +++ b/docs/guides/other_libs/samples/LogDebugSample.cs @@ -0,0 +1 @@ +Log.Debug("Your log message, with {Variables}!", 10); // This will output "[21:51:00 DBG] Your log message, with 10!" diff --git a/docs/guides/other_libs/samples/ModifyLogMethod.cs b/docs/guides/other_libs/samples/ModifyLogMethod.cs new file mode 100644 index 000000000..0f7c11daf --- /dev/null +++ b/docs/guides/other_libs/samples/ModifyLogMethod.cs @@ -0,0 +1,15 @@ +private static async Task LogAsync(LogMessage message) +{ + var severity = message.Severity switch + { + LogSeverity.Critical => LogEventLevel.Fatal, + LogSeverity.Error => LogEventLevel.Error, + LogSeverity.Warning => LogEventLevel.Warning, + LogSeverity.Info => LogEventLevel.Information, + LogSeverity.Verbose => LogEventLevel.Verbose, + LogSeverity.Debug => LogEventLevel.Debug, + _ => LogEventLevel.Information + }; + Log.Write(severity, message.Exception, "[{Source}] {Message}", message.Source, message.Message); + await Task.CompletedTask; +} diff --git a/docs/guides/other_libs/serilog.md b/docs/guides/other_libs/serilog.md new file mode 100644 index 000000000..5086b4b85 --- /dev/null +++ b/docs/guides/other_libs/serilog.md @@ -0,0 +1,45 @@ +--- +uid: Guides.OtherLibs.Serilog +title: Serilog +--- + +# Configuring serilog + +## Prerequisites + +- A basic working bot with a logging method as described in [Creating your first bot](xref:Guides.GettingStarted.FirstBot) + +## Installing the Serilog package + +You can install the following packages through your IDE or go to the nuget link to grab the dotnet cli command. + +|Name|Link| +|--|--| +|`Serilog.Extensions.Logging`| [link](https://www.nuget.org/packages/Serilog.Extensions.Logging)| +|`Serilog.Sinks.Console`| [link](https://www.nuget.org/packages/Serilog.Sinks.Console)| + +## Configuring Serilog + +Serilog will be configured at the top of your async Main method, it looks like this + +[!code-csharp[Configuring serilog](samples/ConfiguringSerilog.cs)] + +## Modifying your logging method + +For Serilog to log Discord events correctly, we have to map the Discord `LogSeverity` to the Serilog `LogEventLevel`. You can modify your log method to look like this. + +[!code-csharp[Modifying your log method](samples/ModifyLogMethod.cs)] + +## Testing + +If you run your application now, you should see something similar to this +![Serilog output](images/serilog_output.png) + +## Using your new logger in other places + +Now that you have set up Serilog, you can use it everywhere in your application by simply calling + +[!code-csharp[Log debug sample](samples/LogDebugSample.cs)] + +> [!NOTE] +> Depending on your configured log level, the log messages may or may not show up in your console. Refer to [Serilog's github page](https://github.com/serilog/serilog/wiki/Configuration-Basics#minimum-level) for more information about log levels. diff --git a/docs/guides/toc.yml b/docs/guides/toc.yml index 1616363b7..b1a6b4721 100644 --- a/docs/guides/toc.yml +++ b/docs/guides/toc.yml @@ -95,7 +95,7 @@ topicUid: Guides.MessageComponents.TextInputs - name: Advanced Concepts topicUid: Guides.MessageComponents.Advanced -- name: Modal Basics +- name: Modal Basics items: - name: Introduction topicUid: Guides.Modals.Intro @@ -109,6 +109,12 @@ topicUid: Guides.GuildEvents.GettingUsers - name: Modifying Events topicUid: Guides.GuildEvents.Modifying +- name: Working with other libraries + items: + - name: Serilog + topicUid: Guides.OtherLibs.Serilog + - name: EFCore + topicUid: Guides.OtherLibs.EFCore - name: Emoji topicUid: Guides.Emoji - name: Voice